Gui: add class TaskDialogPy

This commit is contained in:
wmayer
2022-10-09 14:26:42 +02:00
parent e29d1d0332
commit ff6f04dcc2
5 changed files with 301 additions and 0 deletions

View File

@@ -428,6 +428,7 @@ Application::Application(bool GUIenabled)
Gui::TaskView::ControlPy::init_type();
Py::Module(module).setAttr(std::string("Control"),
Py::Object(Gui::TaskView::ControlPy::getInstance(), true));
Gui::TaskView::TaskDialogPy::init_type();
Base::Interpreter().addType(&LinkViewPy::Type,module,"LinkView");
Base::Interpreter().addType(&AxisOriginPy::Type,module,"AxisOrigin");

View File

@@ -28,6 +28,7 @@
#include <vector>
#include <QDialogButtonBox>
#include <QPointer>
#include <FCGlobal.h>
@@ -39,6 +40,9 @@ namespace Gui {
namespace TaskView {
class TaskContent;
class TaskDialogAttorney;
class TaskDialogPy;
class TaskView;
/// Father class of content with header and Icon
class GuiExport TaskDialog : public QObject
@@ -133,6 +137,7 @@ Q_SIGNALS:
void aboutToBeDestroyed();
protected:
QPointer<QDialogButtonBox> buttonBox;
/// List of TaskBoxes of that dialog
std::vector<QWidget*> Content;
ButtonPosition pos;
@@ -141,6 +146,21 @@ private:
std::string documentName;
bool escapeButton;
bool autoCloseTransaction;
friend class TaskDialogAttorney;
};
class TaskDialogAttorney {
private:
static void setButtonBox(TaskDialog* dlg, QDialogButtonBox* box) {
dlg->buttonBox = box;
}
static QDialogButtonBox* getButtonBox(TaskDialog* dlg) {
return dlg->buttonBox;
}
friend class TaskDialogPy;
friend class TaskView;
};
} //namespace TaskView

View File

@@ -68,6 +68,9 @@ void ControlPy::init_type()
add_varargs_method("activeDialog",&ControlPy::activeDialog,
"check if a dialog is active in the task panel\n"
"activeDialog() --> bool");
add_varargs_method("activeTaskDialog",&ControlPy::activeTaskDialog,
"return the active task dialog if there is one\n"
"activeTaskDialog() --> TaskDialog or None");
add_varargs_method("closeDialog",&ControlPy::closeDialog,
"close the active dialog\n"
"closeDialog()");
@@ -131,6 +134,14 @@ Py::Object ControlPy::activeDialog(const Py::Tuple& args)
return Py::Boolean(dlg != nullptr);
}
Py::Object ControlPy::activeTaskDialog(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), ""))
throw Py::Exception();
Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog();
return (dlg ? Py::asObject(new TaskDialogPy(dlg)) : Py::None());
}
Py::Object ControlPy::closeDialog(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), ""))
@@ -306,6 +317,207 @@ bool TaskWatcherPython::shouldShow()
// ------------------------------------------------------------------
void TaskDialogPy::init_type()
{
behaviors().name("TaskDialog");
behaviors().doc("Task dialog");
// you must have overwritten the virtual functions
behaviors().supportRepr();
behaviors().supportGetattr();
behaviors().supportSetattr();
add_varargs_method("getDialogContent",&TaskDialogPy::getDialogContent,
"Returns the widgets of the task dialog -> list");
add_varargs_method("getStandardButtons",&TaskDialogPy::getStandardButtons,
"Get the standard buttons of the box -> flags");
add_varargs_method("setEscapeButtonEnabled",&TaskDialogPy::setEscapeButtonEnabled,
"Defines whether the task dialog can be rejected by pressing Esc");
add_varargs_method("isEscapeButtonEnabled",&TaskDialogPy::isEscapeButtonEnabled,
"Checks if the task dialog can be rejected by pressing Esc -> bool");
add_varargs_method("setAutoCloseOnTransactionChange",&TaskDialogPy::setAutoCloseOnTransactionChange,
"Defines whether a task dialog must be closed if the document changes the\n"
"active transaction");
add_varargs_method("isAutoCloseOnTransactionChange",&TaskDialogPy::isAutoCloseOnTransactionChange,
"Checks if the task dialog will be closed when the active transaction has changed -> bool");
add_varargs_method("getDocumentName",&TaskDialogPy::getDocumentName,
"Get the name of the document the task dialog is attached to -> str");
add_varargs_method("isAllowedAlterDocument",&TaskDialogPy::isAllowedAlterDocument,
"Indicates whether this task dialog allows other commands to modify\n"
"the document while it is open -> bool");
add_varargs_method("isAllowedAlterView",&TaskDialogPy::isAllowedAlterView,
"Indicates whether this task dialog allows other commands to modify\n"
"the 3d view while it is open -> bool");
add_varargs_method("isAllowedAlterSelection",&TaskDialogPy::isAllowedAlterSelection,
"Indicates whether this task dialog allows other commands to modify\n"
"the selection while it is open -> bool");
add_varargs_method("needsFullSpace",&TaskDialogPy::needsFullSpace,
"Indicates whether the task dialog fully requires the available space -> bool");
add_varargs_method("accept",&TaskDialogPy::accept,
"Accept the task dialog");
add_varargs_method("reject",&TaskDialogPy::reject,
"Reject the task dialog");
}
TaskDialogPy::TaskDialogPy(TaskDialog* dlg)
: dialog(dlg)
{
}
TaskDialogPy::~TaskDialogPy()
{
}
Py::Object TaskDialogPy::repr()
{
std::string s;
std::ostringstream s_out;
s_out << "Task Dialog";
return Py::String(s_out.str());
}
Py::Object TaskDialogPy::getattr(const char * attr)
{
if (!dialog) {
std::ostringstream s_out;
s_out << "Cannot access attribute '" << attr << "' of deleted object";
throw Py::RuntimeError(s_out.str());
}
return BaseType::getattr(attr);
}
int TaskDialogPy::setattr(const char *attr, const Py::Object &value)
{
if (!dialog) {
std::ostringstream s_out;
s_out << "Cannot access attribute '" << attr << "' of deleted object";
throw Py::RuntimeError(s_out.str());
}
return BaseType::setattr(attr, value);
}
Py::Object TaskDialogPy::getDialogContent(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), ""))
throw Py::Exception();
PythonWrapper wrap;
wrap.loadWidgetsModule();
Py::List list;
auto widgets = dialog->getDialogContent();
for (auto it : widgets) {
list.append(wrap.fromQWidget(it));
}
return list;
}
Py::Object TaskDialogPy::getStandardButtons(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), ""))
throw Py::Exception();
auto buttons = dialog->getStandardButtons();
return Py::Long(static_cast<int>(buttons));
}
Py::Object TaskDialogPy::setEscapeButtonEnabled(const Py::Tuple& args)
{
Py::Boolean value(args[0]);
dialog->setEscapeButtonEnabled(static_cast<bool>(value));
return Py::None();
}
Py::Object TaskDialogPy::isEscapeButtonEnabled(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), ""))
throw Py::Exception();
return Py::Boolean(dialog->isEscapeButtonEnabled());
}
Py::Object TaskDialogPy::setAutoCloseOnTransactionChange(const Py::Tuple& args)
{
Py::Boolean value(args[0]);
dialog->setAutoCloseOnTransactionChange(static_cast<bool>(value));
return Py::None();
}
Py::Object TaskDialogPy::isAutoCloseOnTransactionChange(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), ""))
throw Py::Exception();
return Py::Boolean(dialog->isAutoCloseOnTransactionChange());
}
Py::Object TaskDialogPy::getDocumentName(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), ""))
throw Py::Exception();
return Py::String(dialog->getDocumentName());
}
Py::Object TaskDialogPy::isAllowedAlterDocument(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), ""))
throw Py::Exception();
return Py::Boolean(dialog->isAllowedAlterDocument());
}
Py::Object TaskDialogPy::isAllowedAlterView(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), ""))
throw Py::Exception();
return Py::Boolean(dialog->isAllowedAlterView());
}
Py::Object TaskDialogPy::isAllowedAlterSelection(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), ""))
throw Py::Exception();
return Py::Boolean(dialog->isAllowedAlterSelection());
}
Py::Object TaskDialogPy::needsFullSpace(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), ""))
throw Py::Exception();
return Py::Boolean(dialog->needsFullSpace());
}
namespace {
auto clickButton = [](QDialogButtonBox* buttonBox, QDialogButtonBox::ButtonRole role) {
if (buttonBox) {
QList<QAbstractButton*> list = buttonBox->buttons();
for (auto pb : list) {
if (buttonBox->buttonRole(pb) == role) {
if (pb->isEnabled()) {
pb->click();
break;
}
}
}
}
};
}
Py::Object TaskDialogPy::accept(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), ""))
throw Py::Exception();
auto buttonBox = TaskDialogAttorney::getButtonBox(dialog);
clickButton(buttonBox, QDialogButtonBox::AcceptRole);
return Py::None();
}
Py::Object TaskDialogPy::reject(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), ""))
throw Py::Exception();
auto buttonBox = TaskDialogAttorney::getButtonBox(dialog);
clickButton(buttonBox, QDialogButtonBox::RejectRole);
return Py::None();
}
// ------------------------------------------------------------------
TaskDialogPython::TaskDialogPython(const Py::Object& o) : dlg(o)
{
if (dlg.hasAttr(std::string("ui"))) {

View File

@@ -43,6 +43,7 @@ public:
Py::Object repr() override;
Py::Object showDialog(const Py::Tuple&);
Py::Object activeDialog(const Py::Tuple&);
Py::Object activeTaskDialog(const Py::Tuple&);
Py::Object closeDialog(const Py::Tuple&);
Py::Object addTaskWatcher(const Py::Tuple&);
Py::Object clearTaskWatcher(const Py::Tuple&);
@@ -67,6 +68,72 @@ private:
Py::Object watcher;
};
/**
* @brief The TaskDialogPy class
* This class exposes a TaskDialog written in C++ to Python.
*/
class TaskDialogPy : public Py::PythonExtension<TaskDialogPy>
{
public:
using BaseType = Py::PythonExtension<TaskDialogPy>;
static void init_type(); // announce properties and methods
explicit TaskDialogPy(TaskDialog*);
~TaskDialogPy() override;
Py::Object repr() override;
Py::Object getattr(const char *) override;
int setattr(const char *, const Py::Object &) override;
public:
Py::Object getDialogContent(const Py::Tuple&);
/// tells the framework which buttons are wished for the dialog
Py::Object getStandardButtons(const Py::Tuple&);
/// Defines whether a task dialog can be rejected by pressing Esc
Py::Object setEscapeButtonEnabled(const Py::Tuple&);
Py::Object isEscapeButtonEnabled(const Py::Tuple&);
/// Defines whether a task dialog must be closed if the document changed the
/// active transaction.
Py::Object setAutoCloseOnTransactionChange(const Py::Tuple&);
Py::Object isAutoCloseOnTransactionChange(const Py::Tuple&);
Py::Object getDocumentName(const Py::Tuple&);
/*!
Indicates whether this task dialog allows other commands to modify
the document while it is open.
*/
Py::Object isAllowedAlterDocument(const Py::Tuple&);
/*!
Indicates whether this task dialog allows other commands to modify
the 3d view while it is open.
*/
Py::Object isAllowedAlterView(const Py::Tuple&);
/*!
Indicates whether this task dialog allows other commands to modify
the selection while it is open.
*/
Py::Object isAllowedAlterSelection(const Py::Tuple&);
Py::Object needsFullSpace(const Py::Tuple&);
/// is called by the framework if the dialog is accepted (Ok)
Py::Object accept(const Py::Tuple&);
/// is called by the framework if the dialog is rejected (Cancel)
Py::Object reject(const Py::Tuple&);
private:
QPointer<TaskDialog> dialog;
};
/**
* @brief The TaskDialogPython class
* This wraps a task dialog that is written in Python.
*/
class GuiExport TaskDialogPython : public TaskDialog
{
public:

View File

@@ -479,6 +479,7 @@ void TaskView::showDialog(TaskDialog *dlg)
// first create the control element, set it up and wire it:
ActiveCtrl = new TaskEditControl(this);
ActiveCtrl->buttonBox->setStandardButtons(dlg->getStandardButtons());
TaskDialogAttorney::setButtonBox(dlg, ActiveCtrl->buttonBox);
// make connection to the needed signals
connect(ActiveCtrl->buttonBox,SIGNAL(accepted()),