Fem: Implement basic python filter functionality and glyph example

This commit is contained in:
Stefan Tröger
2025-02-13 19:35:10 +01:00
parent bb0c06e8f7
commit 9430bdde01
33 changed files with 1793 additions and 166 deletions

View File

@@ -203,29 +203,33 @@ void DataAlongLineMarker::customEvent(QEvent*)
// ***************************************************************************
// main task dialog
TaskPostBox::TaskPostBox(Gui::ViewProviderDocumentObject* view,
TaskPostWidget::TaskPostWidget(Gui::ViewProviderDocumentObject* view,
const QPixmap& icon,
const QString& title,
QWidget* parent)
: TaskBox(icon, title, true, parent)
: QWidget(parent)
, m_object(view->getObject())
, m_view(view)
{}
{
setWindowTitle(title);
setWindowIcon(icon);
m_icon = icon;
}
TaskPostBox::~TaskPostBox() = default;
TaskPostWidget::~TaskPostWidget() = default;
bool TaskPostBox::autoApply()
bool TaskPostWidget::autoApply()
{
return FemSettings().getPostAutoRecompute();
}
App::Document* TaskPostBox::getDocument() const
App::Document* TaskPostWidget::getDocument() const
{
App::DocumentObject* obj = getObject();
return (obj ? obj->getDocument() : nullptr);
}
void TaskPostBox::recompute()
void TaskPostWidget::recompute()
{
if (autoApply()) {
App::Document* doc = getDocument();
@@ -235,7 +239,7 @@ void TaskPostBox::recompute()
}
}
void TaskPostBox::updateEnumerationList(App::PropertyEnumeration& prop, QComboBox* box)
void TaskPostWidget::updateEnumerationList(App::PropertyEnumeration& prop, QComboBox* box)
{
QStringList list;
std::vector<std::string> vec = prop.getEnumVector();
@@ -266,10 +270,19 @@ TaskDlgPost::~TaskDlgPost() = default;
QDialogButtonBox::StandardButtons TaskDlgPost::getStandardButtons() const
{
// check if we only have gui task boxes
bool guionly = true;
for (auto it : m_boxes) {
guionly = guionly && it->isGuiTaskOnly();
for (auto& widget : Content) {
if(auto task_box = dynamic_cast<Gui::TaskView::TaskBox*>(widget)) {
// get the task widget and check if it is a post widget
auto widget = task_box->groupLayout()->itemAt(0)->widget();
if(auto post_widget = dynamic_cast<TaskPostWidget*>(widget)) {
guionly = guionly && post_widget->isGuiTaskOnly();
} else {
// unknown panel, we can only assume
guionly = false;
}
}
}
if (!guionly) {
@@ -285,7 +298,7 @@ void TaskDlgPost::connectSlots()
// Connect emitAddedFunction() with slotAddedFunction()
QObject* sender = nullptr;
int indexSignal = 0;
for (const auto dlg : m_boxes) {
for (const auto dlg : Content) {
indexSignal = dlg->metaObject()->indexOfSignal(
QMetaObject::normalizedSignature("emitAddedFunction()"));
if (indexSignal >= 0) {
@@ -295,7 +308,7 @@ void TaskDlgPost::connectSlots()
}
if (sender) {
for (const auto dlg : m_boxes) {
for (const auto dlg : Content) {
int indexSlot = dlg->metaObject()->indexOfSlot(
QMetaObject::normalizedSignature("slotAddedFunction()"));
if (indexSlot >= 0) {
@@ -308,12 +321,6 @@ void TaskDlgPost::connectSlots()
}
}
void TaskDlgPost::appendBox(TaskPostBox* box)
{
m_boxes.push_back(box);
Content.push_back(box);
}
void TaskDlgPost::open()
{
// only open a new command if none is pending (e.g. if the object was newly created)
@@ -326,8 +333,14 @@ void TaskDlgPost::open()
void TaskDlgPost::clicked(int button)
{
if (button == QDialogButtonBox::Apply) {
for (auto box : m_boxes) {
box->apply();
for (auto& widget : Content) {
if(auto task_box = dynamic_cast<Gui::TaskView::TaskBox*>(widget)) {
// get the task widget and check if it is a post widget
auto widget = task_box->groupLayout()->itemAt(0)->widget();
if(auto post_widget = dynamic_cast<TaskPostWidget*>(widget)) {
post_widget->apply();
}
}
}
recompute();
}
@@ -336,8 +349,14 @@ void TaskDlgPost::clicked(int button)
bool TaskDlgPost::accept()
{
try {
for (auto& box : m_boxes) {
box->applyPythonCode();
for (auto& widget : Content) {
if(auto task_box = dynamic_cast<Gui::TaskView::TaskBox*>(widget)) {
// get the task widget and check if it is a post widget
auto widget = task_box->groupLayout()->itemAt(0)->widget();
if(auto post_widget = dynamic_cast<TaskPostWidget*>(widget)) {
post_widget->applyPythonCode();
}
}
}
}
catch (const Base::Exception& e) {
@@ -377,19 +396,16 @@ void TaskDlgPost::modifyStandardButtons(QDialogButtonBox* box)
// ***************************************************************************
// box to set the coloring
TaskPostDisplay::TaskPostDisplay(ViewProviderFemPostObject* view, QWidget* parent)
: TaskPostBox(view,
Gui::BitmapFactory().pixmap("FEM_ResultShow"),
tr("Result display options"),
: TaskPostWidget(view,
Gui::BitmapFactory().pixmap("FEM_ResultShow"), QString(),
parent)
, ui(new Ui_TaskPostDisplay)
{
// we need a separate container widget to add all controls to
proxy = new QWidget(this);
ui->setupUi(proxy);
// setup the ui
ui->setupUi(this);
setWindowTitle(tr("Result display options")); // set title here as setupUi overrides the constructor title
setupConnections();
this->groupLayout()->addWidget(proxy);
// update all fields
updateEnumerationList(getTypedView<ViewProviderFemPostObject>()->DisplayMode,
ui->Representation);
@@ -463,7 +479,7 @@ void TaskPostDisplay::applyPythonCode()
// ***************************************************************************
// functions
TaskPostFunction::TaskPostFunction(ViewProviderFemPostFunction* view, QWidget* parent)
: TaskPostBox(view,
: TaskPostWidget(view,
Gui::BitmapFactory().pixmap("fem-post-geo-plane"),
tr("Implicit function"),
parent)
@@ -472,7 +488,10 @@ TaskPostFunction::TaskPostFunction(ViewProviderFemPostFunction* view, QWidget* p
FunctionWidget* w = getTypedView<ViewProviderFemPostFunction>()->createControlWidget();
w->setParent(this);
w->setViewProvider(getTypedView<ViewProviderFemPostFunction>());
this->groupLayout()->addWidget(w);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(w);
setLayout(layout);
}
TaskPostFunction::~TaskPostFunction() = default;
@@ -486,13 +505,12 @@ void TaskPostFunction::applyPythonCode()
// ***************************************************************************
// Frames
TaskPostFrames::TaskPostFrames(ViewProviderFemPostObject* view, QWidget* parent)
: TaskPostBox(view, Gui::BitmapFactory().pixmap("FEM_PostFrames"), tr("Result Frames"), parent)
: TaskPostWidget(view, Gui::BitmapFactory().pixmap("FEM_PostFrames"), QString(), parent)
, ui(new Ui_TaskPostFrames)
{
// we load the views widget
proxy = new QWidget(this);
ui->setupUi(proxy);
this->groupLayout()->addWidget(proxy);
// setup the ui
ui->setupUi(this);
setWindowTitle(tr("Result Frames"));
setupConnections();
// populate the data
@@ -548,16 +566,15 @@ void TaskPostFrames::applyPythonCode()
// ***************************************************************************
// Branch
TaskPostBranch::TaskPostBranch(ViewProviderFemPostBranchFilter* view, QWidget* parent)
: TaskPostBox(view,
: TaskPostWidget(view,
Gui::BitmapFactory().pixmap("FEM_PostBranchFilter"),
tr("Branch behaviour"),
QString(),
parent)
, ui(new Ui_TaskPostBranch)
{
// we load the views widget
proxy = new QWidget(this);
ui->setupUi(proxy);
this->groupLayout()->addWidget(proxy);
// setup the ui
ui->setupUi(this);
setWindowTitle(tr("Branch behaviour"));
setupConnections();
// populate the data
@@ -603,19 +620,17 @@ void TaskPostBranch::applyPythonCode()
// data along line filter
TaskPostDataAlongLine::TaskPostDataAlongLine(ViewProviderFemPostDataAlongLine* view,
QWidget* parent)
: TaskPostBox(view,
: TaskPostWidget(view,
Gui::BitmapFactory().pixmap("FEM_PostFilterDataAlongLine"),
tr("Data along a line options"),
QString(),
parent)
, ui(new Ui_TaskPostDataAlongLine)
, marker(nullptr)
{
// we load the views widget
proxy = new QWidget(this);
ui->setupUi(proxy);
// setup the ui
ui->setupUi(this);
setWindowTitle(tr("Data along a line options"));
setupConnectionsStep1();
this->groupLayout()->addWidget(proxy);
QSize size = ui->point1X->sizeForText(QStringLiteral("000000000000"));
ui->point1X->setMinimumWidth(size.width());
@@ -1025,21 +1040,19 @@ plt.show()\n";
// ***************************************************************************
// data at point filter
TaskPostDataAtPoint::TaskPostDataAtPoint(ViewProviderFemPostDataAtPoint* view, QWidget* parent)
: TaskPostBox(view,
: TaskPostWidget(view,
Gui::BitmapFactory().pixmap("FEM_PostFilterDataAtPoint"),
tr("Data at point options"),
QString(),
parent)
, viewer(nullptr)
, connSelectPoint(QMetaObject::Connection())
, ui(new Ui_TaskPostDataAtPoint)
{
// we load the views widget
proxy = new QWidget(this);
ui->setupUi(proxy);
// setup the ui
ui->setupUi(this);
setWindowTitle(tr("Data at point options"));
setupConnections();
this->groupLayout()->addWidget(proxy);
QSize size = ui->centerX->sizeForText(QStringLiteral("000000000000"));
ui->centerX->setMinimumWidth(size.width());
ui->centerY->setMinimumWidth(size.width());
@@ -1382,9 +1395,9 @@ std::string TaskPostDataAtPoint::toString(double val) const
TaskPostClip::TaskPostClip(ViewProviderFemPostClip* view,
App::PropertyLink* function,
QWidget* parent)
: TaskPostBox(view,
: TaskPostWidget(view,
Gui::BitmapFactory().pixmap("FEM_PostFilterClipRegion"),
tr("Clip region, choose implicit function"),
QString(),
parent)
, ui(new Ui_TaskPostClip)
{
@@ -1393,11 +1406,10 @@ TaskPostClip::TaskPostClip(ViewProviderFemPostClip* view,
fwidget = nullptr;
// we load the views widget
proxy = new QWidget(this);
ui->setupUi(proxy);
// setup the ui
ui->setupUi(this);
setWindowTitle(tr("Clip region, choose implicit function"));
setupConnections();
this->groupLayout()->addWidget(proxy);
// the layout for the container widget
QVBoxLayout* layout = new QVBoxLayout();
@@ -1542,17 +1554,16 @@ void TaskPostClip::onInsideOutToggled(bool val)
// ***************************************************************************
// contours filter
TaskPostContours::TaskPostContours(ViewProviderFemPostContours* view, QWidget* parent)
: TaskPostBox(view,
: TaskPostWidget(view,
Gui::BitmapFactory().pixmap("FEM_PostFilterContours"),
tr("Contours filter options"),
QString(),
parent)
, ui(new Ui_TaskPostContours)
{
// load the views widget
proxy = new QWidget(this);
ui->setupUi(proxy);
// setup the ui
ui->setupUi(this);
setWindowTitle(tr("Contours filter options"));
QMetaObject::connectSlotsByName(this);
this->groupLayout()->addWidget(proxy);
auto obj = getObject<Fem::FemPostContoursFilter>();
@@ -1697,9 +1708,9 @@ void TaskPostContours::onRelaxationChanged(double value)
// ***************************************************************************
// cut filter
TaskPostCut::TaskPostCut(ViewProviderFemPostCut* view, App::PropertyLink* function, QWidget* parent)
: TaskPostBox(view,
: TaskPostWidget(view,
Gui::BitmapFactory().pixmap("FEM_PostFilterCutFunction"),
tr("Function cut, choose implicit function"),
QString(),
parent)
, ui(new Ui_TaskPostCut)
{
@@ -1708,11 +1719,10 @@ TaskPostCut::TaskPostCut(ViewProviderFemPostCut* view, App::PropertyLink* functi
fwidget = nullptr;
// we load the views widget
proxy = new QWidget(this);
ui->setupUi(proxy);
// setup the ui
ui->setupUi(this);
setWindowTitle(tr("Function cut, choose implicit function"));
setupConnections();
this->groupLayout()->addWidget(proxy);
// the layout for the container widget
QVBoxLayout* layout = new QVBoxLayout();
@@ -1836,17 +1846,16 @@ void TaskPostCut::onFunctionBoxCurrentIndexChanged(int idx)
// ***************************************************************************
// scalar clip filter
TaskPostScalarClip::TaskPostScalarClip(ViewProviderFemPostScalarClip* view, QWidget* parent)
: TaskPostBox(view,
: TaskPostWidget(view,
Gui::BitmapFactory().pixmap("FEM_PostFilterClipScalar"),
tr("Scalar clip options"),
QString(),
parent)
, ui(new Ui_TaskPostScalarClip)
{
// we load the views widget
proxy = new QWidget(this);
ui->setupUi(proxy);
// setup the ui
ui->setupUi(this);
setWindowTitle(tr("Scalar clip options"));
setupConnections();
this->groupLayout()->addWidget(proxy);
// load the default values
updateEnumerationList(getTypedObject<Fem::FemPostScalarClipFilter>()->Scalars, ui->Scalar);
@@ -1961,17 +1970,16 @@ void TaskPostScalarClip::onInsideOutToggled(bool val)
// ***************************************************************************
// warp vector filter
TaskPostWarpVector::TaskPostWarpVector(ViewProviderFemPostWarpVector* view, QWidget* parent)
: TaskPostBox(view,
: TaskPostWidget(view,
Gui::BitmapFactory().pixmap("FEM_PostFilterWarp"),
tr("Warp options"),
QString(),
parent)
, ui(new Ui_TaskPostWarpVector)
{
// we load the views widget
proxy = new QWidget(this);
ui->setupUi(proxy);
// setup the ui
ui->setupUi(this);
setWindowTitle(tr("Warp options"));
setupConnections();
this->groupLayout()->addWidget(proxy);
// load the default values for warp display
updateEnumerationList(getTypedObject<Fem::FemPostWarpVectorFilter>()->Vector, ui->Vector);
@@ -2136,17 +2144,15 @@ static const std::vector<std::string> calculatorOperators = {
"log", "pow", "sqrt", "iHat", "jHat", "kHat", "cross", "dot", "mag", "norm"};
TaskPostCalculator::TaskPostCalculator(ViewProviderFemPostCalculator* view, QWidget* parent)
: TaskPostBox(view,
: TaskPostWidget(view,
Gui::BitmapFactory().pixmap("FEM_PostFilterCalculator"),
tr("Calculator options"),
parent)
, ui(new Ui_TaskPostCalculator)
{
// we load the views widget
proxy = new QWidget(this);
ui->setupUi(proxy);
ui->setupUi(this);
setupConnections();
this->groupLayout()->addWidget(proxy);
// load the default values
auto obj = getObject<Fem::FemPostCalculatorFilter>();