[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
This commit is contained in:
@@ -199,7 +199,7 @@ PyObject* FemPostFilterPy::getOutputAlgorithm(PyObject* args)
|
||||
auto algorithm = getFemPostFilterPtr()->getFilterOutput();
|
||||
PyObject* py_algorithm = vtkPythonUtil::GetObjectFromPointer(algorithm);
|
||||
|
||||
return Py::new_reference_to(py_algorithm);
|
||||
return Py::new_reference_to(py_algorithm);
|
||||
#else
|
||||
PyErr_SetString(PyExc_NotImplementedError, "VTK python wrapper not available");
|
||||
Py_Return;
|
||||
|
||||
@@ -30,9 +30,9 @@
|
||||
#include "FemPostObjectPy.cpp"
|
||||
|
||||
#ifdef FC_USE_VTK_PYTHON
|
||||
#include <vtkDataSet.h>
|
||||
#include <vtkPythonUtil.h>
|
||||
#endif //BUILD_FEM_VTK
|
||||
#include <vtkDataSet.h>
|
||||
#include <vtkPythonUtil.h>
|
||||
#endif // BUILD_FEM_VTK
|
||||
|
||||
using namespace Fem;
|
||||
|
||||
@@ -71,7 +71,7 @@ PyObject* FemPostObjectPy::getDataSet(PyObject* args)
|
||||
auto dataset = getFemPostObjectPtr()->getDataSet();
|
||||
if (dataset) {
|
||||
PyObject* py_algorithm = vtkPythonUtil::GetObjectFromPointer(dataset);
|
||||
return Py::new_reference_to(py_algorithm);
|
||||
return Py::new_reference_to(py_algorithm);
|
||||
}
|
||||
return Py_None;
|
||||
#else
|
||||
|
||||
@@ -35,8 +35,8 @@
|
||||
// clang-format on
|
||||
|
||||
#ifdef FC_USE_VTK_PYTHON
|
||||
#include <vtkPythonUtil.h>
|
||||
#endif //BUILD_FEM_VTK
|
||||
#include <vtkPythonUtil.h>
|
||||
#endif // BUILD_FEM_VTK
|
||||
|
||||
|
||||
using namespace Fem;
|
||||
@@ -329,7 +329,7 @@ PyObject* FemPostPipelinePy::getOutputAlgorithm(PyObject* args)
|
||||
auto algorithm = getFemPostPipelinePtr()->getOutputAlgorithm();
|
||||
PyObject* py_algorithm = vtkPythonUtil::GetObjectFromPointer(algorithm);
|
||||
|
||||
return Py::new_reference_to(py_algorithm);
|
||||
return Py::new_reference_to(py_algorithm);
|
||||
#else
|
||||
PyErr_SetString(PyExc_NotImplementedError, "VTK python wrapper not available");
|
||||
Py_Return;
|
||||
|
||||
@@ -213,7 +213,11 @@ TaskPostWidget::TaskPostWidget(Gui::ViewProviderDocumentObject* view,
|
||||
setWindowIcon(icon);
|
||||
m_icon = icon;
|
||||
|
||||
m_connection = m_object->signalChanged.connect(boost::bind(&TaskPostWidget::handlePropertyChange, this, boost::placeholders::_1, boost::placeholders::_2));
|
||||
m_connection =
|
||||
m_object->signalChanged.connect(boost::bind(&TaskPostWidget::handlePropertyChange,
|
||||
this,
|
||||
boost::placeholders::_1,
|
||||
boost::placeholders::_2));
|
||||
}
|
||||
|
||||
TaskPostWidget::~TaskPostWidget()
|
||||
@@ -404,7 +408,8 @@ void TaskDlgPost::modifyStandardButtons(QDialogButtonBox* box)
|
||||
}
|
||||
}
|
||||
|
||||
void TaskDlgPost::processCollapsedWidgets() {
|
||||
void TaskDlgPost::processCollapsedWidgets()
|
||||
{
|
||||
|
||||
for (auto& widget : Content) {
|
||||
auto* task_box = dynamic_cast<Gui::TaskView::TaskBox*>(widget);
|
||||
@@ -417,7 +422,7 @@ void TaskDlgPost::processCollapsedWidgets() {
|
||||
if (!post_widget || !post_widget->initiallyCollapsed()) {
|
||||
continue;
|
||||
}
|
||||
post_widget->setGeometry(QRect(QPoint(0,0), post_widget->sizeHint()));
|
||||
post_widget->setGeometry(QRect(QPoint(0, 0), post_widget->sizeHint()));
|
||||
task_box->hideGroupBox();
|
||||
}
|
||||
}
|
||||
@@ -584,7 +589,8 @@ void TaskPostFrames::applyPythonCode()
|
||||
// we apply the views widgets python code
|
||||
}
|
||||
|
||||
bool TaskPostFrames::initiallyCollapsed() {
|
||||
bool TaskPostFrames::initiallyCollapsed()
|
||||
{
|
||||
|
||||
return (ui->FrameTable->rowCount() == 0);
|
||||
}
|
||||
|
||||
@@ -157,7 +157,8 @@ public:
|
||||
virtual void apply() {};
|
||||
|
||||
// returns if the widget shall be collapsed when opening the task dialog
|
||||
virtual bool initiallyCollapsed() {
|
||||
virtual bool initiallyCollapsed()
|
||||
{
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
@@ -48,9 +48,7 @@ using namespace Gui;
|
||||
// box to handle data extractions
|
||||
|
||||
TaskPostExtraction::TaskPostExtraction(ViewProviderFemPostObject* view, QWidget* parent)
|
||||
: TaskPostWidget(view,
|
||||
Gui::BitmapFactory().pixmap("FEM_PostHistogram"), QString(),
|
||||
parent)
|
||||
: TaskPostWidget(view, Gui::BitmapFactory().pixmap("FEM_PostHistogram"), QString(), parent)
|
||||
{
|
||||
// we load the python implementation, and try to get the widget from it, to add
|
||||
// directly our widget
|
||||
@@ -73,7 +71,7 @@ TaskPostExtraction::TaskPostExtraction(ViewProviderFemPostObject* view, QWidget*
|
||||
m_panel = Py::Object(method.apply(args));
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
Base::PyException e; // extract the Python error text
|
||||
Base::PyException e; // extract the Python error text
|
||||
e.reportException();
|
||||
}
|
||||
|
||||
@@ -97,7 +95,8 @@ TaskPostExtraction::TaskPostExtraction(ViewProviderFemPostObject* view, QWidget*
|
||||
Base::Console().error("Unable to import data extraction widget\n");
|
||||
};
|
||||
|
||||
TaskPostExtraction::~TaskPostExtraction() {
|
||||
TaskPostExtraction::~TaskPostExtraction()
|
||||
{
|
||||
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
@@ -123,7 +122,7 @@ void TaskPostExtraction::onPostDataChanged(Fem::FemPostObject* obj)
|
||||
}
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
Base::PyException e; // extract the Python error text
|
||||
Base::PyException e; // extract the Python error text
|
||||
e.reportException();
|
||||
}
|
||||
};
|
||||
@@ -139,7 +138,7 @@ bool TaskPostExtraction::isGuiTaskOnly()
|
||||
}
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
Base::PyException e; // extract the Python error text
|
||||
Base::PyException e; // extract the Python error text
|
||||
e.reportException();
|
||||
}
|
||||
|
||||
@@ -156,7 +155,7 @@ void TaskPostExtraction::apply()
|
||||
}
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
Base::PyException e; // extract the Python error text
|
||||
Base::PyException e; // extract the Python error text
|
||||
e.reportException();
|
||||
}
|
||||
}
|
||||
@@ -172,7 +171,7 @@ bool TaskPostExtraction::initiallyCollapsed()
|
||||
}
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
Base::PyException e; // extract the Python error text
|
||||
Base::PyException e; // extract the Python error text
|
||||
e.reportException();
|
||||
}
|
||||
|
||||
|
||||
@@ -218,7 +218,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
|
||||
#ifdef FC_USE_VTK_PYTHON
|
||||
<< "FEM_PostVisualization"
|
||||
#endif
|
||||
;
|
||||
;
|
||||
#endif
|
||||
|
||||
Gui::ToolBarItem* utils = new Gui::ToolBarItem(root);
|
||||
@@ -374,7 +374,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const
|
||||
#ifdef FC_USE_VTK_PYTHON
|
||||
<< "FEM_PostVisualization"
|
||||
#endif
|
||||
;
|
||||
;
|
||||
#endif
|
||||
|
||||
Gui::MenuItem* utils = new Gui::MenuItem;
|
||||
|
||||
@@ -83,6 +83,7 @@ class FemWorkbench(Workbench):
|
||||
# check vtk version to potentially find missmatchs
|
||||
if "BUILD_FEM_VTK_PYTHON" in FreeCAD.__cmake__:
|
||||
from femguiutils.vtk_module_handling import vtk_module_handling
|
||||
|
||||
vtk_module_handling()
|
||||
|
||||
def GetClassName(self):
|
||||
|
||||
@@ -696,6 +696,7 @@ def makePostLineplot(doc, name="Lineplot"):
|
||||
post_lineplot.PostLineplot(obj)
|
||||
if FreeCAD.GuiUp:
|
||||
from femviewprovider import view_post_lineplot
|
||||
|
||||
view_post_lineplot.VPPostLineplot(obj.ViewObject)
|
||||
return obj
|
||||
|
||||
@@ -710,6 +711,7 @@ def makePostLineplotFieldData(doc, name="FieldData2D"):
|
||||
post_lineplot.PostLineplotFieldData(obj)
|
||||
if FreeCAD.GuiUp:
|
||||
from femviewprovider import view_post_lineplot
|
||||
|
||||
view_post_lineplot.VPPostLineplotFieldData(obj.ViewObject)
|
||||
return obj
|
||||
|
||||
@@ -724,6 +726,7 @@ def makePostLineplotIndexOverFrames(doc, name="IndexOverFrames2D"):
|
||||
post_lineplot.PostLineplotIndexOverFrames(obj)
|
||||
if FreeCAD.GuiUp:
|
||||
from femviewprovider import view_post_lineplot
|
||||
|
||||
view_post_lineplot.VPPostLineplotIndexOverFrames(obj.ViewObject)
|
||||
return obj
|
||||
|
||||
@@ -738,6 +741,7 @@ def makePostHistogram(doc, name="Histogram"):
|
||||
post_histogram.PostHistogram(obj)
|
||||
if FreeCAD.GuiUp:
|
||||
from femviewprovider import view_post_histogram
|
||||
|
||||
view_post_histogram.VPPostHistogram(obj.ViewObject)
|
||||
return obj
|
||||
|
||||
@@ -752,6 +756,7 @@ def makePostHistogramFieldData(doc, name="FieldData1D"):
|
||||
post_histogram.PostHistogramFieldData(obj)
|
||||
if FreeCAD.GuiUp:
|
||||
from femviewprovider import view_post_histogram
|
||||
|
||||
view_post_histogram.VPPostHistogramFieldData(obj.ViewObject)
|
||||
return obj
|
||||
|
||||
@@ -766,6 +771,7 @@ def makePostHistogramIndexOverFrames(doc, name="IndexOverFrames1D"):
|
||||
post_histogram.PostHistogramIndexOverFrames(obj)
|
||||
if FreeCAD.GuiUp:
|
||||
from femviewprovider import view_post_histogram
|
||||
|
||||
view_post_histogram.VPPostHistogramIndexOverFrames(obj.ViewObject)
|
||||
return obj
|
||||
|
||||
@@ -780,6 +786,7 @@ def makePostTable(doc, name="Table"):
|
||||
post_table.PostTable(obj)
|
||||
if FreeCAD.GuiUp:
|
||||
from femviewprovider import view_post_table
|
||||
|
||||
view_post_table.VPPostTable(obj.ViewObject)
|
||||
return obj
|
||||
|
||||
@@ -794,6 +801,7 @@ def makePostTableFieldData(doc, name="FieldData1D"):
|
||||
post_table.PostTableFieldData(obj)
|
||||
if FreeCAD.GuiUp:
|
||||
from femviewprovider import view_post_table
|
||||
|
||||
view_post_table.VPPostTableFieldData(obj.ViewObject)
|
||||
return obj
|
||||
|
||||
@@ -808,6 +816,7 @@ def makePostTableIndexOverFrames(doc, name="IndexOverFrames1D"):
|
||||
post_table.PostTableIndexOverFrames(obj)
|
||||
if FreeCAD.GuiUp:
|
||||
from femviewprovider import view_post_table
|
||||
|
||||
view_post_table.VPPostTableIndexOverFrames(obj.ViewObject)
|
||||
return obj
|
||||
|
||||
|
||||
@@ -1231,6 +1231,7 @@ class _PostFilterGlyph(CommandManager):
|
||||
self.is_active = "with_vtk_selresult"
|
||||
self.do_activated = "add_filter_set_edit"
|
||||
|
||||
|
||||
# the string in add command will be the page name on FreeCAD wiki
|
||||
FreeCADGui.addCommand("FEM_Analysis", _Analysis())
|
||||
FreeCADGui.addCommand("FEM_ClippingPlaneAdd", _ClippingPlaneAdd())
|
||||
@@ -1295,4 +1296,5 @@ if "BUILD_FEM_VTK_PYTHON" in FreeCAD.__cmake__:
|
||||
import femobjects.post_table
|
||||
|
||||
from femguiutils import post_visualization
|
||||
|
||||
post_visualization.setup_commands("FEM_PostVisualization")
|
||||
|
||||
@@ -381,6 +381,7 @@ class CommandManager:
|
||||
|
||||
# check if we should use python filter
|
||||
from femguiutils.vtk_module_handling import vtk_compatibility_abort
|
||||
|
||||
if vtk_compatibility_abort(True):
|
||||
return
|
||||
|
||||
|
||||
@@ -37,8 +37,7 @@ from vtkmodules.vtkCommonCore import vtkVersion
|
||||
from vtkmodules.vtkCommonDataModel import vtkTable
|
||||
from vtkmodules.vtkFiltersGeneral import vtkSplitColumnComponents
|
||||
|
||||
if vtkVersion.GetVTKMajorVersion() > 9 and \
|
||||
vtkVersion.GetVTKMinorVersion() > 3:
|
||||
if vtkVersion.GetVTKMajorVersion() > 9 and vtkVersion.GetVTKMinorVersion() > 3:
|
||||
from vtkmodules.vtkFiltersCore import vtkAttributeDataToTableFilter
|
||||
else:
|
||||
from vtkmodules.vtkInfovisCore import vtkDataObjectToTable
|
||||
@@ -51,6 +50,7 @@ import femobjects.base_fempostextractors as extr
|
||||
from femtaskpanels.base_fempostpanel import _BasePostTaskPanel
|
||||
|
||||
from . import extract_link_view
|
||||
|
||||
ExtractLinkView = extract_link_view.ExtractLinkView
|
||||
|
||||
|
||||
@@ -83,11 +83,10 @@ class DataExtraction(_BasePostTaskPanel):
|
||||
|
||||
# setup the extraction widget
|
||||
self._extraction_view = ExtractLinkView(self.Object, True, self)
|
||||
self.widget.layout().addSpacing(self.widget.Data.size().height()/3)
|
||||
self.widget.layout().addSpacing(self.widget.Data.size().height() / 3)
|
||||
self.widget.layout().addWidget(self._extraction_view)
|
||||
self._extraction_view.repopulate()
|
||||
|
||||
|
||||
@QtCore.Slot()
|
||||
def showData(self):
|
||||
|
||||
@@ -96,7 +95,7 @@ class DataExtraction(_BasePostTaskPanel):
|
||||
widget = vtk_table_view.VtkTableView(self.data_model)
|
||||
layout = QtGui.QVBoxLayout()
|
||||
layout.addWidget(widget)
|
||||
layout.setContentsMargins(0,0,0,0)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
dialog.setLayout(layout)
|
||||
dialog.resize(1500, 900)
|
||||
@@ -110,7 +109,7 @@ class DataExtraction(_BasePostTaskPanel):
|
||||
widget = vtk_table_view.VtkTableView(self.summary_model)
|
||||
layout = QtGui.QVBoxLayout()
|
||||
layout.addWidget(widget)
|
||||
layout.setContentsMargins(0,0,0,0)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
dialog.setLayout(layout)
|
||||
dialog.resize(600, 900)
|
||||
@@ -126,8 +125,7 @@ class DataExtraction(_BasePostTaskPanel):
|
||||
if not algo:
|
||||
self.data_model.setTable(vtkTable())
|
||||
|
||||
if vtkVersion.GetVTKMajorVersion() > 9 and \
|
||||
vtkVersion.GetVTKMinorVersion() > 3:
|
||||
if vtkVersion.GetVTKMajorVersion() > 9 and vtkVersion.GetVTKMinorVersion() > 3:
|
||||
filter = vtkAttributeDataToTableFilter()
|
||||
else:
|
||||
filter = vtkDataObjectToTable()
|
||||
|
||||
@@ -44,6 +44,7 @@ translate = FreeCAD.Qt.translate
|
||||
# a model showing available visualizations and possible extractions
|
||||
# #################################################################
|
||||
|
||||
|
||||
def build_new_visualization_tree_model():
|
||||
# model that shows all options to create new visualizations
|
||||
|
||||
@@ -67,6 +68,7 @@ def build_new_visualization_tree_model():
|
||||
|
||||
return model
|
||||
|
||||
|
||||
def build_add_to_visualization_tree_model():
|
||||
# model that shows all possible visualization objects to add data to
|
||||
|
||||
@@ -92,7 +94,9 @@ def build_add_to_visualization_tree_model():
|
||||
for ext in visualizations[vis_type].extractions:
|
||||
icon = FreeCADGui.getIcon(ext.icon)
|
||||
name = ext.name.removeprefix(vis_type)
|
||||
ext_item = QtGui.QStandardItem(icon, translate("FEM", "Add {}").format(name))
|
||||
ext_item = QtGui.QStandardItem(
|
||||
icon, translate("FEM", "Add {}").format(name)
|
||||
)
|
||||
ext_item.setFlags(QtGui.Qt.ItemIsEnabled)
|
||||
ext_item.setData(ext)
|
||||
vis_item.appendRow(ext_item)
|
||||
@@ -102,10 +106,13 @@ def build_add_to_visualization_tree_model():
|
||||
|
||||
return model
|
||||
|
||||
|
||||
def build_post_object_item(post_object, extractions, vis_type):
|
||||
|
||||
# definitely build a item and add the extractions
|
||||
post_item = QtGui.QStandardItem(post_object.ViewObject.Icon, translate("FEM", "From {}").format(post_object.Label))
|
||||
post_item = QtGui.QStandardItem(
|
||||
post_object.ViewObject.Icon, translate("FEM", "From {}").format(post_object.Label)
|
||||
)
|
||||
post_item.setFlags(QtGui.Qt.ItemIsEnabled)
|
||||
post_item.setData(post_object)
|
||||
|
||||
@@ -150,9 +157,11 @@ def build_add_from_data_tree_model(vis_type):
|
||||
|
||||
return model
|
||||
|
||||
|
||||
# implementation of GUI and its functionality
|
||||
# ###########################################
|
||||
|
||||
|
||||
class _ElideToolButton(QtGui.QToolButton):
|
||||
# tool button that elides its text, and left align icon and text
|
||||
|
||||
@@ -174,7 +183,7 @@ class _ElideToolButton(QtGui.QToolButton):
|
||||
button_size = super().sizeHint()
|
||||
icn_size = self.iconSize()
|
||||
min_margin = max((button_size - icn_size).height(), 6)
|
||||
return QtCore.QSize(self.iconSize().width()+10, icn_size.height() + min_margin)
|
||||
return QtCore.QSize(self.iconSize().width() + 10, icn_size.height() + min_margin)
|
||||
|
||||
def paintEvent(self, event):
|
||||
|
||||
@@ -190,11 +199,10 @@ class _ElideToolButton(QtGui.QToolButton):
|
||||
margin = (self.height() - self.iconSize().height()) / 2
|
||||
icn_width = self.iconSize().width()
|
||||
if self._icon.isNull():
|
||||
icn_width = 0;
|
||||
|
||||
icn_width = 0
|
||||
|
||||
fm = self.fontMetrics()
|
||||
txt_size = self.width() - icn_width - 2*margin
|
||||
txt_size = self.width() - icn_width - 2 * margin
|
||||
if not self._icon.isNull():
|
||||
# we add the margin between icon and text
|
||||
txt_size -= margin
|
||||
@@ -205,7 +213,7 @@ class _ElideToolButton(QtGui.QToolButton):
|
||||
xpos = margin
|
||||
if not self._icon.isNull() and txt_size < txt_min:
|
||||
# center icon
|
||||
xpos = self.width()/2 - self.iconSize().width()/2
|
||||
xpos = self.width() / 2 - self.iconSize().width() / 2
|
||||
|
||||
if not self._icon.isNull():
|
||||
match type(self._icon):
|
||||
@@ -213,10 +221,12 @@ class _ElideToolButton(QtGui.QToolButton):
|
||||
painter.drawPixmap(xpos, margin, self._icon.scaled(self.iconSize()))
|
||||
xpos += self.iconSize().width()
|
||||
case QtGui.QIcon:
|
||||
self._icon.paint(painter, QtCore.QRect(QtCore.QPoint(margin, margin), self.iconSize()))
|
||||
self._icon.paint(
|
||||
painter, QtCore.QRect(QtCore.QPoint(margin, margin), self.iconSize())
|
||||
)
|
||||
xpos += self.iconSize().width()
|
||||
|
||||
xpos += margin # the margin to the text
|
||||
xpos += margin # the margin to the text
|
||||
|
||||
if txt_size >= txt_min:
|
||||
text = fm.elidedText(self._text, QtGui.Qt.ElideMiddle, txt_size)
|
||||
@@ -227,7 +237,7 @@ class _ElideToolButton(QtGui.QToolButton):
|
||||
|
||||
class _TreeChoiceButton(QtGui.QToolButton):
|
||||
|
||||
selection = QtCore.Signal(object,object)
|
||||
selection = QtCore.Signal(object, object)
|
||||
|
||||
def __init__(self, model):
|
||||
super().__init__()
|
||||
@@ -254,9 +264,10 @@ class _TreeChoiceButton(QtGui.QToolButton):
|
||||
self.popup = QtGui.QWidgetAction(self)
|
||||
self.popup.setDefaultWidget(self.tree_view)
|
||||
self.setPopupMode(QtGui.QToolButton.InstantPopup)
|
||||
self.addAction(self.popup);
|
||||
self.addAction(self.popup)
|
||||
|
||||
QtCore.Slot(QtCore.QModelIndex)
|
||||
|
||||
def selectIndex(self, index):
|
||||
item = self.model.itemFromIndex(index)
|
||||
|
||||
@@ -274,6 +285,7 @@ class _TreeChoiceButton(QtGui.QToolButton):
|
||||
# check if we should be disabled
|
||||
self.setEnabled(bool(model.rowCount()))
|
||||
|
||||
|
||||
class _SettingsPopup(QtGui.QMenu):
|
||||
|
||||
close = QtCore.Signal()
|
||||
@@ -297,7 +309,7 @@ class _SettingsPopup(QtGui.QMenu):
|
||||
widget.setLayout(vbox)
|
||||
|
||||
vbox2 = QtGui.QVBoxLayout()
|
||||
vbox2.setContentsMargins(0,0,0,0)
|
||||
vbox2.setContentsMargins(0, 0, 0, 0)
|
||||
vbox2.addWidget(widget)
|
||||
self.setLayout(vbox2)
|
||||
|
||||
@@ -321,7 +333,7 @@ class _SettingsPopup(QtGui.QMenu):
|
||||
|
||||
class _SummaryWidget(QtGui.QWidget):
|
||||
|
||||
delete = QtCore.Signal(object, object) # to delete: document object, summary widget
|
||||
delete = QtCore.Signal(object, object) # to delete: document object, summary widget
|
||||
|
||||
def __init__(self, st_object, extractor, post_dialog):
|
||||
super().__init__()
|
||||
@@ -335,17 +347,16 @@ class _SummaryWidget(QtGui.QWidget):
|
||||
|
||||
# build the UI
|
||||
hbox = QtGui.QHBoxLayout()
|
||||
hbox.setContentsMargins(6,0,6,0)
|
||||
hbox.setContentsMargins(6, 0, 6, 0)
|
||||
hbox.setSpacing(2)
|
||||
|
||||
self.extrButton = self._button(extractor.ViewObject.Icon, extr_label)
|
||||
self.viewButton = self._button(extr_repr[0], extr_repr[1], 1)
|
||||
|
||||
size = self.viewButton.iconSize()
|
||||
size.setWidth(size.width()*2)
|
||||
size.setWidth(size.width() * 2)
|
||||
self.viewButton.setIconSize(size)
|
||||
|
||||
|
||||
if st_object:
|
||||
self.stButton = self._button(st_object.ViewObject.Icon, st_object.Label)
|
||||
hbox.addWidget(self.stButton)
|
||||
@@ -357,7 +368,9 @@ class _SummaryWidget(QtGui.QWidget):
|
||||
self.viewButton.hide()
|
||||
|
||||
self.warning = QtGui.QLabel(self)
|
||||
self.warning.full_text = translate("FEM", "{}: Data source not available").format(extractor.Label)
|
||||
self.warning.full_text = translate("FEM", "{}: Data source not available").format(
|
||||
extractor.Label
|
||||
)
|
||||
hbox.addWidget(self.warning)
|
||||
|
||||
self.rmButton = QtGui.QToolButton(self)
|
||||
@@ -371,16 +384,16 @@ class _SummaryWidget(QtGui.QWidget):
|
||||
|
||||
# add the separation line
|
||||
vbox = QtGui.QVBoxLayout()
|
||||
vbox.setContentsMargins(0,0,0,0)
|
||||
vbox.setContentsMargins(0, 0, 0, 0)
|
||||
vbox.setSpacing(5)
|
||||
vbox.addItem(hbox)
|
||||
self.frame = QtGui.QFrame(self)
|
||||
self.frame.setFrameShape(QtGui.QFrame.HLine);
|
||||
self.frame.setFrameShape(QtGui.QFrame.HLine)
|
||||
vbox.addWidget(self.frame)
|
||||
|
||||
policy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred)
|
||||
self.setSizePolicy(policy)
|
||||
#self.setMinimumSize(self.extrButton.sizeHint()+self.frame.sizeHint()*3)
|
||||
# self.setMinimumSize(self.extrButton.sizeHint()+self.frame.sizeHint()*3)
|
||||
self.setLayout(vbox)
|
||||
|
||||
# connect actions. We add functions to widget, as well as the data we need,
|
||||
@@ -393,8 +406,7 @@ class _SummaryWidget(QtGui.QWidget):
|
||||
self.rmButton.clicked.connect(self.deleteTriggered)
|
||||
|
||||
# make sure initial drawing happened
|
||||
#self._redraw()
|
||||
|
||||
# self._redraw()
|
||||
|
||||
def _button(self, icon, text, stretch=2):
|
||||
|
||||
@@ -408,7 +420,6 @@ class _SummaryWidget(QtGui.QWidget):
|
||||
btn.setSizePolicy(policy)
|
||||
return btn
|
||||
|
||||
|
||||
@QtCore.Slot()
|
||||
def showVisualization(self):
|
||||
if vis.is_visualization_object(self._st_object):
|
||||
@@ -426,14 +437,18 @@ class _SummaryWidget(QtGui.QWidget):
|
||||
# very weird values. Hence we build the coords of the widget
|
||||
# ourself
|
||||
|
||||
summary = dialog.parent() # == self
|
||||
summary = dialog.parent() # == self
|
||||
base_widget = summary.parent()
|
||||
viewport = summary.parent()
|
||||
scroll = viewport.parent()
|
||||
|
||||
top_left = summary.geometry().topLeft() + base_widget.geometry().topLeft() + viewport.geometry().topLeft()
|
||||
delta = (summary.width() - dialog.size().width())/2
|
||||
local_point = QtCore.QPoint(top_left.x()+delta, top_left.y()+summary.height())
|
||||
top_left = (
|
||||
summary.geometry().topLeft()
|
||||
+ base_widget.geometry().topLeft()
|
||||
+ viewport.geometry().topLeft()
|
||||
)
|
||||
delta = (summary.width() - dialog.size().width()) / 2
|
||||
local_point = QtCore.QPoint(top_left.x() + delta, top_left.y() + summary.height())
|
||||
global_point = scroll.mapToGlobal(local_point)
|
||||
|
||||
dialog.setGeometry(QtCore.QRect(global_point, dialog.sizeHint()))
|
||||
@@ -485,7 +500,6 @@ class _SummaryWidget(QtGui.QWidget):
|
||||
self.extrButton.setToolTip(extr_label)
|
||||
|
||||
|
||||
|
||||
class ExtractLinkView(QtGui.QWidget):
|
||||
|
||||
def __init__(self, obj, is_source, post_dialog):
|
||||
@@ -506,7 +520,7 @@ class ExtractLinkView(QtGui.QWidget):
|
||||
self._scroll_view.setWidgetResizable(True)
|
||||
self._scroll_widget = QtGui.QWidget(self._scroll_view)
|
||||
vbox = QtGui.QVBoxLayout()
|
||||
vbox.setContentsMargins(0,6,0,0)
|
||||
vbox.setContentsMargins(0, 6, 0, 0)
|
||||
vbox.addStretch()
|
||||
self._scroll_widget.setLayout(vbox)
|
||||
self._scroll_view.setWidget(self._scroll_widget)
|
||||
@@ -541,7 +555,7 @@ class ExtractLinkView(QtGui.QWidget):
|
||||
hbox.addWidget(self._add)
|
||||
|
||||
vbox = QtGui.QVBoxLayout()
|
||||
vbox.setContentsMargins(0,0,0,0)
|
||||
vbox.setContentsMargins(0, 0, 0, 0)
|
||||
vbox.addItem(hbox)
|
||||
vbox.addWidget(self._scroll_view)
|
||||
|
||||
@@ -616,7 +630,8 @@ class ExtractLinkView(QtGui.QWidget):
|
||||
|
||||
return None
|
||||
|
||||
QtCore.Slot(object, object) # visualization data, extraction data
|
||||
QtCore.Slot(object, object) # visualization data, extraction data
|
||||
|
||||
def newVisualization(self, vis_data, ext_data):
|
||||
|
||||
FreeCADGui.addModule(vis_data.module)
|
||||
@@ -630,17 +645,13 @@ class ExtractLinkView(QtGui.QWidget):
|
||||
|
||||
analysis = self._find_parent_analysis(self._object)
|
||||
if analysis:
|
||||
FreeCADGui.doCommand(
|
||||
f"FreeCAD.ActiveDocument.{analysis.Name}.addObject(visualization)"
|
||||
)
|
||||
FreeCADGui.doCommand(f"FreeCAD.ActiveDocument.{analysis.Name}.addObject(visualization)")
|
||||
|
||||
# create extraction and add it
|
||||
FreeCADGui.doCommand(
|
||||
f"extraction = {ext_data.module}.{ext_data.factory}(FreeCAD.ActiveDocument)"
|
||||
)
|
||||
FreeCADGui.doCommand(
|
||||
f"extraction.Source = FreeCAD.ActiveDocument.{self._object.Name}"
|
||||
)
|
||||
FreeCADGui.doCommand(f"extraction.Source = FreeCAD.ActiveDocument.{self._object.Name}")
|
||||
# default values: color
|
||||
color_prop = FreeCADGui.ActiveDocument.ActiveObject.Proxy.get_default_color_property()
|
||||
if color_prop:
|
||||
@@ -648,15 +659,13 @@ class ExtractLinkView(QtGui.QWidget):
|
||||
f"extraction.ViewObject.{color_prop} = visualization.ViewObject.Proxy.get_next_default_color()"
|
||||
)
|
||||
|
||||
FreeCADGui.doCommand(
|
||||
f"visualization.addObject(extraction)"
|
||||
)
|
||||
|
||||
FreeCADGui.doCommand(f"visualization.addObject(extraction)")
|
||||
|
||||
self._post_dialog._recompute()
|
||||
self.repopulate()
|
||||
|
||||
QtCore.Slot(object, object) # visualization object, extraction data
|
||||
QtCore.Slot(object, object) # visualization object, extraction data
|
||||
|
||||
def addExtractionToVisualization(self, vis_obj, ext_data):
|
||||
|
||||
FreeCADGui.addModule(ext_data.module)
|
||||
@@ -666,9 +675,7 @@ class ExtractLinkView(QtGui.QWidget):
|
||||
FreeCADGui.doCommand(
|
||||
f"extraction = {ext_data.module}.{ext_data.factory}(FreeCAD.ActiveDocument)"
|
||||
)
|
||||
FreeCADGui.doCommand(
|
||||
f"extraction.Source = FreeCAD.ActiveDocument.{self._object.Name}"
|
||||
)
|
||||
FreeCADGui.doCommand(f"extraction.Source = FreeCAD.ActiveDocument.{self._object.Name}")
|
||||
|
||||
# default values: color
|
||||
color_prop = FreeCADGui.ActiveDocument.ActiveObject.Proxy.get_default_color_property()
|
||||
@@ -677,14 +684,13 @@ class ExtractLinkView(QtGui.QWidget):
|
||||
f"extraction.ViewObject.{color_prop} = (Gui.ActiveDocument.{vis_obj.Name}.Proxy.get_next_default_color())"
|
||||
)
|
||||
|
||||
FreeCADGui.doCommand(
|
||||
f"App.ActiveDocument.{vis_obj.Name}.addObject(extraction)"
|
||||
)
|
||||
FreeCADGui.doCommand(f"App.ActiveDocument.{vis_obj.Name}.addObject(extraction)")
|
||||
|
||||
self._post_dialog._recompute()
|
||||
self.repopulate()
|
||||
|
||||
QtCore.Slot(object, object) # post object, extraction data
|
||||
QtCore.Slot(object, object) # post object, extraction data
|
||||
|
||||
def addExtractionToPostObject(self, post_obj, ext_data):
|
||||
|
||||
FreeCADGui.addModule(ext_data.module)
|
||||
@@ -694,9 +700,7 @@ class ExtractLinkView(QtGui.QWidget):
|
||||
FreeCADGui.doCommand(
|
||||
f"extraction = {ext_data.module}.{ext_data.factory}(FreeCAD.ActiveDocument)"
|
||||
)
|
||||
FreeCADGui.doCommand(
|
||||
f"extraction.Source = FreeCAD.ActiveDocument.{post_obj.Name}"
|
||||
)
|
||||
FreeCADGui.doCommand(f"extraction.Source = FreeCAD.ActiveDocument.{post_obj.Name}")
|
||||
|
||||
# default values for color
|
||||
color_prop = FreeCADGui.ActiveDocument.ActiveObject.Proxy.get_default_color_property()
|
||||
@@ -705,10 +709,7 @@ class ExtractLinkView(QtGui.QWidget):
|
||||
f"extraction.ViewObject.{color_prop} = Gui.ActiveDocument.{self._object.Name}.Proxy.get_next_default_color()"
|
||||
)
|
||||
|
||||
FreeCADGui.doCommand(
|
||||
f"App.ActiveDocument.{self._object.Name}.addObject(extraction)"
|
||||
)
|
||||
FreeCADGui.doCommand(f"App.ActiveDocument.{self._object.Name}.addObject(extraction)")
|
||||
|
||||
self._post_dialog._recompute()
|
||||
self.repopulate()
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ import FreeCAD
|
||||
|
||||
_registry = {}
|
||||
|
||||
|
||||
@dataclass
|
||||
class _Extraction:
|
||||
|
||||
@@ -55,6 +56,7 @@ class _Extraction:
|
||||
module: str
|
||||
factory: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class _Visualization:
|
||||
|
||||
@@ -64,6 +66,7 @@ class _Visualization:
|
||||
factory: str
|
||||
extractions: list[_Extraction]
|
||||
|
||||
|
||||
# Register a visualization by type, icon and factory function
|
||||
def register_visualization(visualization_type, icon, module, factory):
|
||||
if visualization_type in _registry:
|
||||
@@ -71,7 +74,10 @@ def register_visualization(visualization_type, icon, module, factory):
|
||||
|
||||
_registry[visualization_type] = _Visualization(visualization_type, icon, module, factory, [])
|
||||
|
||||
def register_extractor(visualization_type, extraction_type, icon, dimension, etype, module, factory):
|
||||
|
||||
def register_extractor(
|
||||
visualization_type, extraction_type, icon, dimension, etype, module, factory
|
||||
):
|
||||
|
||||
if not visualization_type in _registry:
|
||||
raise ValueError("visualization not registered yet")
|
||||
@@ -79,6 +85,7 @@ def register_extractor(visualization_type, extraction_type, icon, dimension, ety
|
||||
extraction = _Extraction(extraction_type, icon, dimension, etype, module, factory)
|
||||
_registry[visualization_type].extractions.append(extraction)
|
||||
|
||||
|
||||
def get_registered_visualizations():
|
||||
return copy.deepcopy(_registry)
|
||||
|
||||
@@ -86,6 +93,7 @@ def get_registered_visualizations():
|
||||
def _to_command_name(name):
|
||||
return "FEM_PostVisualization" + name
|
||||
|
||||
|
||||
class _VisualizationGroupCommand:
|
||||
|
||||
def GetCommands(self):
|
||||
@@ -97,14 +105,19 @@ class _VisualizationGroupCommand:
|
||||
return 0
|
||||
|
||||
def GetResources(self):
|
||||
return { 'MenuText': QtCore.QT_TRANSLATE_NOOP("FEM", 'Data Visualizations'),
|
||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("FEM", 'Different visualizations to show post processing data in')}
|
||||
return {
|
||||
"MenuText": QtCore.QT_TRANSLATE_NOOP("FEM", "Data Visualizations"),
|
||||
"ToolTip": QtCore.QT_TRANSLATE_NOOP(
|
||||
"FEM", "Different visualizations to show post processing data in"
|
||||
),
|
||||
}
|
||||
|
||||
def IsActive(self):
|
||||
if not FreeCAD.ActiveDocument:
|
||||
return False
|
||||
|
||||
import FemGui
|
||||
|
||||
return bool(FemGui.getActiveAnalysis())
|
||||
|
||||
|
||||
@@ -120,12 +133,12 @@ class _VisualizationCommand:
|
||||
tooltip = f"Create a {self._visualization_type} post processing data visualization"
|
||||
|
||||
return {
|
||||
"Pixmap": vis.icon,
|
||||
"MenuText": QtCore.QT_TRANSLATE_NOOP(cmd, "Create {}".format(self._visualization_type)),
|
||||
"Accel": "",
|
||||
"ToolTip": QtCore.QT_TRANSLATE_NOOP(cmd, tooltip),
|
||||
"CmdType": "AlterDoc"
|
||||
}
|
||||
"Pixmap": vis.icon,
|
||||
"MenuText": QtCore.QT_TRANSLATE_NOOP(cmd, "Create {}".format(self._visualization_type)),
|
||||
"Accel": "",
|
||||
"ToolTip": QtCore.QT_TRANSLATE_NOOP(cmd, tooltip),
|
||||
"CmdType": "AlterDoc",
|
||||
}
|
||||
|
||||
def IsActive(self):
|
||||
# active analysis available
|
||||
@@ -133,6 +146,7 @@ class _VisualizationCommand:
|
||||
return False
|
||||
|
||||
import FemGui
|
||||
|
||||
return bool(FemGui.getActiveAnalysis())
|
||||
|
||||
def Activated(self):
|
||||
@@ -144,17 +158,12 @@ class _VisualizationCommand:
|
||||
FreeCADGui.addModule(vis.module)
|
||||
FreeCADGui.addModule("FemGui")
|
||||
|
||||
FreeCADGui.doCommand(
|
||||
f"obj = {vis.module}.{vis.factory}(FreeCAD.ActiveDocument)"
|
||||
)
|
||||
FreeCADGui.doCommand(
|
||||
f"FemGui.getActiveAnalysis().addObject(obj)"
|
||||
)
|
||||
FreeCADGui.doCommand(f"obj = {vis.module}.{vis.factory}(FreeCAD.ActiveDocument)")
|
||||
FreeCADGui.doCommand(f"FemGui.getActiveAnalysis().addObject(obj)")
|
||||
|
||||
FreeCADGui.Selection.clearSelection()
|
||||
FreeCADGui.doCommand(
|
||||
"FreeCADGui.ActiveDocument.setEdit(obj)"
|
||||
)
|
||||
FreeCADGui.doCommand("FreeCADGui.ActiveDocument.setEdit(obj)")
|
||||
|
||||
|
||||
def setup_commands(toplevel_name):
|
||||
# creates all visualization commands and registers them. The
|
||||
|
||||
@@ -39,13 +39,14 @@ from vtkmodules.vtkIOCore import vtkDelimitedTextWriter
|
||||
|
||||
translate = FreeCAD.Qt.translate
|
||||
|
||||
|
||||
class VtkTableModel(QtCore.QAbstractTableModel):
|
||||
# Simple table model. Only supports single component columns
|
||||
# One can supply a header_names dict to replace the table column names
|
||||
# in the header. It is a dict "column_idx (int)" to "new name"" or
|
||||
# "orig_name (str)" to "new name"
|
||||
|
||||
def __init__(self, header_names = None):
|
||||
def __init__(self, header_names=None):
|
||||
super().__init__()
|
||||
self._table = None
|
||||
if header_names:
|
||||
@@ -53,7 +54,7 @@ class VtkTableModel(QtCore.QAbstractTableModel):
|
||||
else:
|
||||
self._header = {}
|
||||
|
||||
def setTable(self, table, header_names = None):
|
||||
def setTable(self, table, header_names=None):
|
||||
self.beginResetModel()
|
||||
self._table = table
|
||||
if header_names:
|
||||
@@ -105,6 +106,7 @@ class VtkTableModel(QtCore.QAbstractTableModel):
|
||||
def getTable(self):
|
||||
return self._table
|
||||
|
||||
|
||||
class VtkTableSummaryModel(QtCore.QAbstractTableModel):
|
||||
# Simple model showing a summary of the table.
|
||||
# Only supports single component columns
|
||||
@@ -126,7 +128,7 @@ class VtkTableSummaryModel(QtCore.QAbstractTableModel):
|
||||
return self._table.GetNumberOfColumns()
|
||||
|
||||
def columnCount(self, index):
|
||||
return 2 # min, max
|
||||
return 2 # min, max
|
||||
|
||||
def data(self, index, role):
|
||||
|
||||
@@ -143,7 +145,7 @@ class VtkTableSummaryModel(QtCore.QAbstractTableModel):
|
||||
def headerData(self, section, orientation, role):
|
||||
|
||||
if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
|
||||
return ["Min","Max"][section]
|
||||
return ["Min", "Max"][section]
|
||||
|
||||
if orientation == QtCore.Qt.Vertical and role == QtCore.Qt.DisplayRole:
|
||||
return self._table.GetColumnName(section)
|
||||
@@ -162,7 +164,7 @@ class VtkTableView(QtGui.QWidget):
|
||||
self.model = model
|
||||
|
||||
layout = QtGui.QVBoxLayout()
|
||||
layout.setContentsMargins(0,0,0,0)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
layout.setSpacing(0)
|
||||
|
||||
# start with the toolbar
|
||||
@@ -177,7 +179,9 @@ class VtkTableView(QtGui.QWidget):
|
||||
copy_action.triggered.connect(self.copyToClipboard)
|
||||
copy_action.setIcon(FreeCADGui.getIcon("edit-copy"))
|
||||
shortcut = QtGui.QKeySequence(QtGui.QKeySequence.Copy)
|
||||
copy_action.setToolTip(translate("FEM", "Copy selection to clipboard ({})".format(shortcut.toString())))
|
||||
copy_action.setToolTip(
|
||||
translate("FEM", "Copy selection to clipboard ({})".format(shortcut.toString()))
|
||||
)
|
||||
copy_action.setShortcut(shortcut)
|
||||
self.toolbar.addAction(copy_action)
|
||||
|
||||
@@ -205,15 +209,19 @@ class VtkTableView(QtGui.QWidget):
|
||||
@QtCore.Slot(bool)
|
||||
def exportCsv(self, state):
|
||||
|
||||
file_path, filter = QtGui.QFileDialog.getSaveFileName(None, translate("FEM", "Save as csv file"), "", "CSV (*.csv)")
|
||||
file_path, filter = QtGui.QFileDialog.getSaveFileName(
|
||||
None, translate("FEM", "Save as csv file"), "", "CSV (*.csv)"
|
||||
)
|
||||
if not file_path:
|
||||
FreeCAD.Console.PrintMessage(translate("FEM", "CSV file export aborted: no filename selected"))
|
||||
FreeCAD.Console.PrintMessage(
|
||||
translate("FEM", "CSV file export aborted: no filename selected")
|
||||
)
|
||||
return
|
||||
|
||||
writer = vtkDelimitedTextWriter()
|
||||
writer.SetFileName(file_path)
|
||||
writer.SetInputData(self.model.getTable());
|
||||
writer.Write();
|
||||
writer.SetInputData(self.model.getTable())
|
||||
writer.Write()
|
||||
|
||||
@QtCore.Slot()
|
||||
def copyToClipboard(self):
|
||||
@@ -228,19 +236,18 @@ class VtkTableView(QtGui.QWidget):
|
||||
previous = selection.pop(0)
|
||||
for current in selection:
|
||||
|
||||
data = self.model.data(previous, QtCore.Qt.DisplayRole);
|
||||
data = self.model.data(previous, QtCore.Qt.DisplayRole)
|
||||
copy_table += str(data)
|
||||
|
||||
if current.row() != previous.row():
|
||||
copy_table += '\n'
|
||||
copy_table += "\n"
|
||||
else:
|
||||
copy_table += '\t'
|
||||
copy_table += "\t"
|
||||
|
||||
previous = current
|
||||
|
||||
copy_table += str(self.model.data(selection[-1], QtCore.Qt.DisplayRole))
|
||||
copy_table += '\n'
|
||||
copy_table += "\n"
|
||||
|
||||
clipboard = QtGui.QApplication.instance().clipboard()
|
||||
clipboard.setText(copy_table)
|
||||
|
||||
|
||||
@@ -36,22 +36,26 @@ from vtkmodules.vtkCommonDataModel import vtkTable
|
||||
from PySide.QtCore import QT_TRANSLATE_NOOP
|
||||
|
||||
from . import base_fempythonobject
|
||||
|
||||
_PropHelper = base_fempythonobject._PropHelper
|
||||
|
||||
# helper functions
|
||||
# ################
|
||||
|
||||
|
||||
def is_extractor_object(obj):
|
||||
if not hasattr(obj, "Proxy"):
|
||||
return False
|
||||
|
||||
return hasattr(obj.Proxy, "ExtractionType")
|
||||
|
||||
|
||||
def get_extraction_type(obj):
|
||||
# returns the extractor type string, or throws exception if
|
||||
# not a extractor
|
||||
return obj.Proxy.ExtractionType
|
||||
|
||||
|
||||
def get_extraction_dimension(obj):
|
||||
# returns the extractor dimension string, or throws exception if
|
||||
# not a extractor
|
||||
@@ -104,7 +108,6 @@ class Extractor(base_fempythonobject.BaseFemPythonObject):
|
||||
FreeCAD.Console.PrintWarning("Invalid object: Line source must be FemPostObject")
|
||||
obj.Source = None
|
||||
|
||||
|
||||
def get_vtk_table(self, obj):
|
||||
if not obj.DataTable:
|
||||
obj.DataTable = vtkTable()
|
||||
@@ -135,7 +138,6 @@ class Extractor1D(Extractor):
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
|
||||
|
||||
def _get_properties(self):
|
||||
prop = [
|
||||
_PropHelper(
|
||||
@@ -149,14 +151,15 @@ class Extractor1D(Extractor):
|
||||
type="App::PropertyEnumeration",
|
||||
name="XComponent",
|
||||
group="X Data",
|
||||
doc=QT_TRANSLATE_NOOP("FEM", "Which part of the X field vector to use for the X axis"),
|
||||
doc=QT_TRANSLATE_NOOP(
|
||||
"FEM", "Which part of the X field vector to use for the X axis"
|
||||
),
|
||||
value=[],
|
||||
),
|
||||
]
|
||||
|
||||
return super()._get_properties() + prop
|
||||
|
||||
|
||||
def onChanged(self, obj, prop):
|
||||
|
||||
super().onChanged(obj, prop)
|
||||
@@ -213,7 +216,7 @@ class Extractor1D(Extractor):
|
||||
if array.GetNumberOfComponents() == 1:
|
||||
table.AddColumn(array)
|
||||
else:
|
||||
component_array = vtkDoubleArray();
|
||||
component_array = vtkDoubleArray()
|
||||
component_array.SetNumberOfComponents(1)
|
||||
component_array.SetNumberOfTuples(array.GetNumberOfTuples())
|
||||
c_idx = obj.getEnumerationsOfProperty("XComponent").index(obj.XComponent)
|
||||
@@ -233,7 +236,7 @@ class Extractor1D(Extractor):
|
||||
array.SetNumberOfTuples(num)
|
||||
array.SetNumberOfComponents(1)
|
||||
for i in range(num):
|
||||
array.SetValue(i,i)
|
||||
array.SetValue(i, i)
|
||||
|
||||
case "Position":
|
||||
|
||||
@@ -266,6 +269,7 @@ class Extractor1D(Extractor):
|
||||
|
||||
return label
|
||||
|
||||
|
||||
class Extractor2D(Extractor1D):
|
||||
|
||||
ExtractionDimension = "2D"
|
||||
@@ -273,7 +277,6 @@ class Extractor2D(Extractor1D):
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
|
||||
|
||||
def _get_properties(self):
|
||||
prop = [
|
||||
_PropHelper(
|
||||
@@ -287,14 +290,15 @@ class Extractor2D(Extractor1D):
|
||||
type="App::PropertyEnumeration",
|
||||
name="YComponent",
|
||||
group="Y Data",
|
||||
doc=QT_TRANSLATE_NOOP("FEM", "Which part of the Y field vector to use for the Y axis"),
|
||||
doc=QT_TRANSLATE_NOOP(
|
||||
"FEM", "Which part of the Y field vector to use for the Y axis"
|
||||
),
|
||||
value=[],
|
||||
),
|
||||
]
|
||||
|
||||
return super()._get_properties() + prop
|
||||
|
||||
|
||||
def onChanged(self, obj, prop):
|
||||
|
||||
super().onChanged(obj, prop)
|
||||
@@ -348,7 +352,7 @@ class Extractor2D(Extractor1D):
|
||||
if array.GetNumberOfComponents() == 1:
|
||||
table.AddColumn(array)
|
||||
else:
|
||||
component_array = vtkDoubleArray();
|
||||
component_array = vtkDoubleArray()
|
||||
component_array.SetNumberOfComponents(1)
|
||||
component_array.SetNumberOfTuples(array.GetNumberOfTuples())
|
||||
c_idx = obj.getEnumerationsOfProperty("YComponent").index(obj.YComponent)
|
||||
|
||||
@@ -38,6 +38,7 @@ from . import base_fempostextractors
|
||||
# helper functions
|
||||
# ################
|
||||
|
||||
|
||||
def is_visualization_object(obj):
|
||||
if not obj:
|
||||
return False
|
||||
@@ -71,27 +72,23 @@ def is_visualization_extractor_type(obj, vistype):
|
||||
return True
|
||||
|
||||
|
||||
|
||||
# Base class for all visualizations
|
||||
# It collects all data from its extraction objects into a table.
|
||||
# Note: Never use directly, always subclass! This class does not create a
|
||||
# Visualization variable, hence will not work correctly.
|
||||
class PostVisualization(base_fempythonobject.BaseFemPythonObject):
|
||||
|
||||
|
||||
def __init__(self, obj):
|
||||
super().__init__(obj)
|
||||
obj.addExtension("App::GroupExtensionPython")
|
||||
self._setup_properties(obj)
|
||||
|
||||
|
||||
def _setup_properties(self, obj):
|
||||
pl = obj.PropertiesList
|
||||
for prop in self._get_properties():
|
||||
if not prop.name in pl:
|
||||
prop.add_to_object(obj)
|
||||
|
||||
|
||||
def _get_properties(self):
|
||||
# override if subclass wants to add additional properties
|
||||
|
||||
@@ -106,14 +103,12 @@ class PostVisualization(base_fempythonobject.BaseFemPythonObject):
|
||||
]
|
||||
return prop
|
||||
|
||||
|
||||
def onDocumentRestored(self, obj):
|
||||
# if a new property was added we handle it by setup
|
||||
# Override if subclass needs to handle changed property type
|
||||
|
||||
self._setup_properties(obj)
|
||||
|
||||
|
||||
def onChanged(self, obj, prop):
|
||||
# Ensure only correct child object types are in the group
|
||||
|
||||
@@ -123,13 +118,14 @@ class PostVisualization(base_fempythonobject.BaseFemPythonObject):
|
||||
children = obj.Group
|
||||
for child in obj.Group:
|
||||
if not is_visualization_extractor_type(child, self.VisualizationType):
|
||||
FreeCAD.Console.PrintWarning(f"{child.Label} is not a {self.VisualizationType} extraction object, cannot be added")
|
||||
FreeCAD.Console.PrintWarning(
|
||||
f"{child.Label} is not a {self.VisualizationType} extraction object, cannot be added"
|
||||
)
|
||||
children.remove(child)
|
||||
|
||||
if len(obj.Group) != len(children):
|
||||
obj.Group = children
|
||||
|
||||
|
||||
def execute(self, obj):
|
||||
# Collect all extractor child data into our table
|
||||
# Note: Each childs table can have different number of rows. We need
|
||||
@@ -144,7 +140,9 @@ class PostVisualization(base_fempythonobject.BaseFemPythonObject):
|
||||
# to none without recompute, and the visualization was manually
|
||||
# recomputed afterwards
|
||||
if not child.Source and (child.Table.GetNumberOfColumns() > 0):
|
||||
FreeCAD.Console.PrintWarning(f"{child.Label} has data, but no Source object. Will be ignored")
|
||||
FreeCAD.Console.PrintWarning(
|
||||
f"{child.Label} has data, but no Source object. Will be ignored"
|
||||
)
|
||||
continue
|
||||
|
||||
c_table = child.Table
|
||||
@@ -159,18 +157,16 @@ class PostVisualization(base_fempythonobject.BaseFemPythonObject):
|
||||
else:
|
||||
array.SetNumberOfComponents(c_array.GetNumberOfComponents())
|
||||
array.SetNumberOfTuples(rows)
|
||||
array.Fill(0) # so that all non-used entries are set to 0
|
||||
array.Fill(0) # so that all non-used entries are set to 0
|
||||
for j in range(c_array.GetNumberOfTuples()):
|
||||
array.SetTuple(j, c_array.GetTuple(j))
|
||||
|
||||
array.SetName(f"{child.Source.Name}: {c_array.GetName()}")
|
||||
table.AddColumn(array)
|
||||
|
||||
|
||||
obj.Table = table
|
||||
return False
|
||||
|
||||
|
||||
def getLongestColumnLength(self, obj):
|
||||
# iterate all extractor children and get the column lengths
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import FreeCAD
|
||||
|
||||
from . import base_fempostextractors
|
||||
from . import base_fempythonobject
|
||||
|
||||
_PropHelper = base_fempythonobject._PropHelper
|
||||
|
||||
from vtkmodules.vtkCommonCore import vtkDoubleArray
|
||||
@@ -53,11 +54,14 @@ class PostFieldData1D(base_fempostextractors.Extractor1D):
|
||||
super().__init__(obj)
|
||||
|
||||
def _get_properties(self):
|
||||
prop =[ _PropHelper(
|
||||
prop = [
|
||||
_PropHelper(
|
||||
type="App::PropertyBool",
|
||||
name="ExtractFrames",
|
||||
group="Multiframe",
|
||||
doc=QT_TRANSLATE_NOOP("FEM", "Specify if the field shall be extracted for every available frame"),
|
||||
doc=QT_TRANSLATE_NOOP(
|
||||
"FEM", "Specify if the field shall be extracted for every available frame"
|
||||
),
|
||||
value=False,
|
||||
),
|
||||
]
|
||||
@@ -77,14 +81,16 @@ class PostFieldData1D(base_fempostextractors.Extractor1D):
|
||||
obj.Table = table
|
||||
return
|
||||
|
||||
timesteps=[]
|
||||
timesteps = []
|
||||
if obj.ExtractFrames:
|
||||
# check if we have timesteps
|
||||
info = obj.Source.getOutputAlgorithm().GetOutputInformation(0)
|
||||
if info.Has(vtkStreamingDemandDrivenPipeline.TIME_STEPS()):
|
||||
timesteps = info.Get(vtkStreamingDemandDrivenPipeline.TIME_STEPS())
|
||||
else:
|
||||
FreeCAD.Console.PrintWarning("No frames available in data, ignoring \"ExtractFrames\" property")
|
||||
FreeCAD.Console.PrintWarning(
|
||||
'No frames available in data, ignoring "ExtractFrames" property'
|
||||
)
|
||||
|
||||
if not timesteps:
|
||||
# get the dataset and extract the correct array
|
||||
@@ -124,11 +130,14 @@ class PostIndexOverFrames1D(base_fempostextractors.Extractor1D):
|
||||
super().__init__(obj)
|
||||
|
||||
def _get_properties(self):
|
||||
prop =[_PropHelper(
|
||||
prop = [
|
||||
_PropHelper(
|
||||
type="App::PropertyInteger",
|
||||
name="Index",
|
||||
group="X Data",
|
||||
doc=QT_TRANSLATE_NOOP("FEM", "Specify for which index the data should be extracted"),
|
||||
doc=QT_TRANSLATE_NOOP(
|
||||
"FEM", "Specify for which index the data should be extracted"
|
||||
),
|
||||
value=0,
|
||||
),
|
||||
]
|
||||
@@ -154,7 +163,6 @@ class PostIndexOverFrames1D(base_fempostextractors.Extractor1D):
|
||||
if info.Has(vtkStreamingDemandDrivenPipeline.TIME_STEPS()):
|
||||
timesteps = info.Get(vtkStreamingDemandDrivenPipeline.TIME_STEPS())
|
||||
|
||||
|
||||
algo = obj.Source.getOutputAlgorithm()
|
||||
frame_array = vtkDoubleArray()
|
||||
idx = obj.Index
|
||||
@@ -168,8 +176,10 @@ class PostIndexOverFrames1D(base_fempostextractors.Extractor1D):
|
||||
array = self._x_array_from_dataset(obj, dataset, copy=False)
|
||||
|
||||
# safeguard for invalid access
|
||||
if idx < 0 or array.GetNumberOfTuples()-1 < idx:
|
||||
raise Exception(f"Invalid index: {idx} is not in range 0 - {array.GetNumberOfTuples()-1}")
|
||||
if idx < 0 or array.GetNumberOfTuples() - 1 < idx:
|
||||
raise Exception(
|
||||
f"Invalid index: {idx} is not in range 0 - {array.GetNumberOfTuples()-1}"
|
||||
)
|
||||
|
||||
if not setup:
|
||||
frame_array.SetNumberOfComponents(array.GetNumberOfComponents())
|
||||
@@ -183,14 +193,15 @@ class PostIndexOverFrames1D(base_fempostextractors.Extractor1D):
|
||||
array = self._x_array_from_dataset(obj, dataset, copy=False)
|
||||
|
||||
# safeguard for invalid access
|
||||
if idx < 0 or array.GetNumberOfTuples()-1 < idx:
|
||||
raise Exception(f"Invalid index: {idx} is not in range 0 - {array.GetNumberOfTuples()-1}")
|
||||
if idx < 0 or array.GetNumberOfTuples() - 1 < idx:
|
||||
raise Exception(
|
||||
f"Invalid index: {idx} is not in range 0 - {array.GetNumberOfTuples()-1}"
|
||||
)
|
||||
|
||||
frame_array.SetNumberOfComponents(array.GetNumberOfComponents())
|
||||
frame_array.SetNumberOfTuples(1)
|
||||
frame_array.SetTuple(0, idx, array)
|
||||
|
||||
|
||||
if frame_array.GetNumberOfComponents() > 1:
|
||||
frame_array.SetName(f"{obj.XField} ({obj.XComponent}) @Idx {obj.Index}")
|
||||
else:
|
||||
|
||||
@@ -33,6 +33,7 @@ import FreeCAD
|
||||
|
||||
from . import base_fempostextractors
|
||||
from . import base_fempythonobject
|
||||
|
||||
_PropHelper = base_fempythonobject._PropHelper
|
||||
|
||||
from vtkmodules.vtkCommonCore import vtkDoubleArray
|
||||
@@ -53,17 +54,19 @@ class PostFieldData2D(base_fempostextractors.Extractor2D):
|
||||
super().__init__(obj)
|
||||
|
||||
def _get_properties(self):
|
||||
prop =[ _PropHelper(
|
||||
prop = [
|
||||
_PropHelper(
|
||||
type="App::PropertyBool",
|
||||
name="ExtractFrames",
|
||||
group="Multiframe",
|
||||
doc=QT_TRANSLATE_NOOP("FEM", "Specify if the field shall be extracted for every available frame"),
|
||||
doc=QT_TRANSLATE_NOOP(
|
||||
"FEM", "Specify if the field shall be extracted for every available frame"
|
||||
),
|
||||
value=False,
|
||||
),
|
||||
]
|
||||
return super()._get_properties() + prop
|
||||
|
||||
|
||||
def execute(self, obj):
|
||||
|
||||
# on execution we populate the vtk table
|
||||
@@ -85,7 +88,9 @@ class PostFieldData2D(base_fempostextractors.Extractor2D):
|
||||
if info.Has(vtkStreamingDemandDrivenPipeline.TIME_STEPS()):
|
||||
timesteps = info.Get(vtkStreamingDemandDrivenPipeline.TIME_STEPS())
|
||||
else:
|
||||
FreeCAD.Console.PrintWarning("No frames available in data, ignoring \"ExtractFrames\" property")
|
||||
FreeCAD.Console.PrintWarning(
|
||||
'No frames available in data, ignoring "ExtractFrames" property'
|
||||
)
|
||||
|
||||
if not timesteps:
|
||||
# get the dataset and extract the correct array
|
||||
@@ -140,11 +145,14 @@ class PostIndexOverFrames2D(base_fempostextractors.Extractor2D):
|
||||
super().__init__(obj)
|
||||
|
||||
def _get_properties(self):
|
||||
prop =[_PropHelper(
|
||||
prop = [
|
||||
_PropHelper(
|
||||
type="App::PropertyInteger",
|
||||
name="Index",
|
||||
group="Data",
|
||||
doc=QT_TRANSLATE_NOOP("FEM", "Specify for which point index the data should be extracted"),
|
||||
doc=QT_TRANSLATE_NOOP(
|
||||
"FEM", "Specify for which point index the data should be extracted"
|
||||
),
|
||||
value=0,
|
||||
),
|
||||
]
|
||||
@@ -178,7 +186,6 @@ class PostIndexOverFrames2D(base_fempostextractors.Extractor2D):
|
||||
if info.Has(vtkStreamingDemandDrivenPipeline.TIME_STEPS()):
|
||||
timesteps = info.Get(vtkStreamingDemandDrivenPipeline.TIME_STEPS())
|
||||
|
||||
|
||||
algo = obj.Source.getOutputAlgorithm()
|
||||
|
||||
frame_x_array = vtkDoubleArray()
|
||||
@@ -198,8 +205,10 @@ class PostIndexOverFrames2D(base_fempostextractors.Extractor2D):
|
||||
array = self._y_array_from_dataset(obj, dataset, copy=False)
|
||||
|
||||
# safeguard for invalid access
|
||||
if idx < 0 or array.GetNumberOfTuples()-1 < idx:
|
||||
raise Exception(f"Invalid index: {idx} is not in range 0 - {array.GetNumberOfTuples()-1}")
|
||||
if idx < 0 or array.GetNumberOfTuples() - 1 < idx:
|
||||
raise Exception(
|
||||
f"Invalid index: {idx} is not in range 0 - {array.GetNumberOfTuples()-1}"
|
||||
)
|
||||
|
||||
if not setup:
|
||||
frame_y_array.SetNumberOfComponents(array.GetNumberOfComponents())
|
||||
@@ -211,21 +220,22 @@ class PostIndexOverFrames2D(base_fempostextractors.Extractor2D):
|
||||
else:
|
||||
frame_x_array.SetNumberOfTuples(1)
|
||||
frame_x_array.SetNumberOfComponents(1)
|
||||
frame_x_array.SetTuple1(0,0)
|
||||
frame_x_array.SetTuple1(0, 0)
|
||||
|
||||
algo.Update()
|
||||
dataset = algo.GetOutputDataObject(0)
|
||||
array = self._y_array_from_dataset(obj, dataset, copy=False)
|
||||
|
||||
# safeguard for invalid access
|
||||
if idx < 0 or array.GetNumberOfTuples()-1 < idx:
|
||||
raise Exception(f"Invalid index: {idx} is not in range 0 - {array.GetNumberOfTuples()-1}")
|
||||
if idx < 0 or array.GetNumberOfTuples() - 1 < idx:
|
||||
raise Exception(
|
||||
f"Invalid index: {idx} is not in range 0 - {array.GetNumberOfTuples()-1}"
|
||||
)
|
||||
|
||||
frame_y_array.SetNumberOfComponents(array.GetNumberOfComponents())
|
||||
frame_y_array.SetNumberOfTuples(1)
|
||||
frame_y_array.SetTuple(0, idx, array)
|
||||
|
||||
|
||||
frame_x_array.SetName("Frames")
|
||||
if frame_y_array.GetNumberOfComponents() > 1:
|
||||
frame_y_array.SetName(f"{obj.YField} ({obj.YComponent}) @Idx {obj.Index}")
|
||||
|
||||
@@ -33,6 +33,7 @@ import FreeCAD
|
||||
|
||||
# check vtk version to potentially find missmatchs
|
||||
from femguiutils.vtk_module_handling import vtk_module_handling
|
||||
|
||||
vtk_module_handling()
|
||||
|
||||
# IMPORTANT: Never import vtk directly. Often vtk is compiled with different QT
|
||||
|
||||
@@ -31,6 +31,7 @@ __url__ = "https://www.freecad.org"
|
||||
|
||||
# check vtk version to potentially find missmatchs
|
||||
from femguiutils.vtk_module_handling import vtk_module_handling
|
||||
|
||||
vtk_module_handling()
|
||||
|
||||
from . import base_fempostextractors
|
||||
@@ -40,31 +41,35 @@ from . import post_extract1D
|
||||
from femguiutils import post_visualization
|
||||
|
||||
# register visualization and extractors
|
||||
post_visualization.register_visualization("Histogram",
|
||||
":/icons/FEM_PostHistogram.svg",
|
||||
"ObjectsFem",
|
||||
"makePostHistogram")
|
||||
post_visualization.register_visualization(
|
||||
"Histogram", ":/icons/FEM_PostHistogram.svg", "ObjectsFem", "makePostHistogram"
|
||||
)
|
||||
|
||||
post_visualization.register_extractor("Histogram",
|
||||
"HistogramFieldData",
|
||||
":/icons/FEM_PostField.svg",
|
||||
"1D",
|
||||
"Field",
|
||||
"ObjectsFem",
|
||||
"makePostHistogramFieldData")
|
||||
post_visualization.register_extractor(
|
||||
"Histogram",
|
||||
"HistogramFieldData",
|
||||
":/icons/FEM_PostField.svg",
|
||||
"1D",
|
||||
"Field",
|
||||
"ObjectsFem",
|
||||
"makePostHistogramFieldData",
|
||||
)
|
||||
|
||||
|
||||
post_visualization.register_extractor("Histogram",
|
||||
"HistogramIndexOverFrames",
|
||||
":/icons/FEM_PostIndex.svg",
|
||||
"1D",
|
||||
"Index",
|
||||
"ObjectsFem",
|
||||
"makePostHistogramIndexOverFrames")
|
||||
post_visualization.register_extractor(
|
||||
"Histogram",
|
||||
"HistogramIndexOverFrames",
|
||||
":/icons/FEM_PostIndex.svg",
|
||||
"1D",
|
||||
"Index",
|
||||
"ObjectsFem",
|
||||
"makePostHistogramIndexOverFrames",
|
||||
)
|
||||
|
||||
# Implementation
|
||||
# ##############
|
||||
|
||||
|
||||
def is_histogram_extractor(obj):
|
||||
|
||||
if not base_fempostextractors.is_extractor_object(obj):
|
||||
@@ -80,6 +85,7 @@ class PostHistogramFieldData(post_extract1D.PostFieldData1D):
|
||||
"""
|
||||
A 1D Field extraction for histograms.
|
||||
"""
|
||||
|
||||
VisualizationType = "Histogram"
|
||||
|
||||
|
||||
@@ -87,6 +93,7 @@ class PostHistogramIndexOverFrames(post_extract1D.PostIndexOverFrames1D):
|
||||
"""
|
||||
A 1D index extraction for histogram.
|
||||
"""
|
||||
|
||||
VisualizationType = "Histogram"
|
||||
|
||||
|
||||
@@ -94,13 +101,5 @@ class PostHistogram(base_fempostvisualizations.PostVisualization):
|
||||
"""
|
||||
A post processing plot for showing extracted data as histograms
|
||||
"""
|
||||
|
||||
VisualizationType = "Histogram"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ __url__ = "https://www.freecad.org"
|
||||
|
||||
# check vtk version to potentially find missmatchs
|
||||
from femguiutils.vtk_module_handling import vtk_module_handling
|
||||
|
||||
vtk_module_handling()
|
||||
|
||||
from . import base_fempostextractors
|
||||
@@ -40,31 +41,35 @@ from . import post_extract2D
|
||||
from femguiutils import post_visualization
|
||||
|
||||
# register visualization and extractors
|
||||
post_visualization.register_visualization("Lineplot",
|
||||
":/icons/FEM_PostLineplot.svg",
|
||||
"ObjectsFem",
|
||||
"makePostLineplot")
|
||||
post_visualization.register_visualization(
|
||||
"Lineplot", ":/icons/FEM_PostLineplot.svg", "ObjectsFem", "makePostLineplot"
|
||||
)
|
||||
|
||||
post_visualization.register_extractor("Lineplot",
|
||||
"LineplotFieldData",
|
||||
":/icons/FEM_PostField.svg",
|
||||
"2D",
|
||||
"Field",
|
||||
"ObjectsFem",
|
||||
"makePostLineplotFieldData")
|
||||
post_visualization.register_extractor(
|
||||
"Lineplot",
|
||||
"LineplotFieldData",
|
||||
":/icons/FEM_PostField.svg",
|
||||
"2D",
|
||||
"Field",
|
||||
"ObjectsFem",
|
||||
"makePostLineplotFieldData",
|
||||
)
|
||||
|
||||
post_visualization.register_extractor("Lineplot",
|
||||
"LineplotIndexOverFrames",
|
||||
":/icons/FEM_PostIndex.svg",
|
||||
"2D",
|
||||
"Index",
|
||||
"ObjectsFem",
|
||||
"makePostLineplotIndexOverFrames")
|
||||
post_visualization.register_extractor(
|
||||
"Lineplot",
|
||||
"LineplotIndexOverFrames",
|
||||
":/icons/FEM_PostIndex.svg",
|
||||
"2D",
|
||||
"Index",
|
||||
"ObjectsFem",
|
||||
"makePostLineplotIndexOverFrames",
|
||||
)
|
||||
|
||||
|
||||
# Implementation
|
||||
# ##############
|
||||
|
||||
|
||||
def is_lineplot_extractor(obj):
|
||||
|
||||
if not base_fempostextractors.is_extractor_object(obj):
|
||||
@@ -80,6 +85,7 @@ class PostLineplotFieldData(post_extract2D.PostFieldData2D):
|
||||
"""
|
||||
A 2D Field extraction for lineplot.
|
||||
"""
|
||||
|
||||
VisualizationType = "Lineplot"
|
||||
|
||||
|
||||
@@ -87,15 +93,13 @@ class PostLineplotIndexOverFrames(post_extract2D.PostIndexOverFrames2D):
|
||||
"""
|
||||
A 2D index extraction for lineplot.
|
||||
"""
|
||||
VisualizationType = "Lineplot"
|
||||
|
||||
VisualizationType = "Lineplot"
|
||||
|
||||
|
||||
class PostLineplot(base_fempostvisualizations.PostVisualization):
|
||||
"""
|
||||
A post processing plot for showing extracted data as line plots
|
||||
"""
|
||||
|
||||
VisualizationType = "Lineplot"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ __url__ = "https://www.freecad.org"
|
||||
|
||||
# check vtk version to potentially find missmatchs
|
||||
from femguiutils.vtk_module_handling import vtk_module_handling
|
||||
|
||||
vtk_module_handling()
|
||||
|
||||
from . import base_fempostextractors
|
||||
@@ -40,31 +41,35 @@ from . import post_extract1D
|
||||
from femguiutils import post_visualization
|
||||
|
||||
# register visualization and extractors
|
||||
post_visualization.register_visualization("Table",
|
||||
":/icons/FEM_PostSpreadsheet.svg",
|
||||
"ObjectsFem",
|
||||
"makePostTable")
|
||||
post_visualization.register_visualization(
|
||||
"Table", ":/icons/FEM_PostSpreadsheet.svg", "ObjectsFem", "makePostTable"
|
||||
)
|
||||
|
||||
post_visualization.register_extractor("Table",
|
||||
"TableFieldData",
|
||||
":/icons/FEM_PostField.svg",
|
||||
"1D",
|
||||
"Field",
|
||||
"ObjectsFem",
|
||||
"makePostTableFieldData")
|
||||
post_visualization.register_extractor(
|
||||
"Table",
|
||||
"TableFieldData",
|
||||
":/icons/FEM_PostField.svg",
|
||||
"1D",
|
||||
"Field",
|
||||
"ObjectsFem",
|
||||
"makePostTableFieldData",
|
||||
)
|
||||
|
||||
|
||||
post_visualization.register_extractor("Table",
|
||||
"TableIndexOverFrames",
|
||||
":/icons/FEM_PostIndex.svg",
|
||||
"1D",
|
||||
"Index",
|
||||
"ObjectsFem",
|
||||
"makePostTableIndexOverFrames")
|
||||
post_visualization.register_extractor(
|
||||
"Table",
|
||||
"TableIndexOverFrames",
|
||||
":/icons/FEM_PostIndex.svg",
|
||||
"1D",
|
||||
"Index",
|
||||
"ObjectsFem",
|
||||
"makePostTableIndexOverFrames",
|
||||
)
|
||||
|
||||
# Implementation
|
||||
# ##############
|
||||
|
||||
|
||||
def is_table_extractor(obj):
|
||||
|
||||
if not base_fempostextractors.is_extractor_object(obj):
|
||||
@@ -80,6 +85,7 @@ class PostTableFieldData(post_extract1D.PostFieldData1D):
|
||||
"""
|
||||
A 1D Field extraction for tables.
|
||||
"""
|
||||
|
||||
VisualizationType = "Table"
|
||||
|
||||
|
||||
@@ -87,6 +93,7 @@ class PostTableIndexOverFrames(post_extract1D.PostIndexOverFrames1D):
|
||||
"""
|
||||
A 1D index extraction for table.
|
||||
"""
|
||||
|
||||
VisualizationType = "Table"
|
||||
|
||||
|
||||
@@ -94,6 +101,5 @@ class PostTable(base_fempostvisualizations.PostVisualization):
|
||||
"""
|
||||
A post processing plot for showing extracted data as tables
|
||||
"""
|
||||
|
||||
VisualizationType = "Table"
|
||||
|
||||
|
||||
|
||||
@@ -53,7 +53,9 @@ class _BasePostTaskPanel(base_femtaskpanel._BaseTaskPanel):
|
||||
# ##########################
|
||||
|
||||
def getStandardButtons(self):
|
||||
return QtGui.QDialogButtonBox.Apply | QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel
|
||||
return (
|
||||
QtGui.QDialogButtonBox.Apply | QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel
|
||||
)
|
||||
|
||||
def clicked(self, button):
|
||||
# apply button hit?
|
||||
@@ -63,8 +65,9 @@ class _BasePostTaskPanel(base_femtaskpanel._BaseTaskPanel):
|
||||
def open(self):
|
||||
# open a new transaction if non is open
|
||||
if not FreeCAD.getActiveTransaction():
|
||||
FreeCAD.ActiveDocument.openTransaction(translate("FEM", "Edit {}").format(self.obj.Label))
|
||||
|
||||
FreeCAD.ActiveDocument.openTransaction(
|
||||
translate("FEM", "Edit {}").format(self.obj.Label)
|
||||
)
|
||||
|
||||
# Helper functions
|
||||
# ################
|
||||
@@ -83,6 +86,3 @@ class _BasePostTaskPanel(base_femtaskpanel._BaseTaskPanel):
|
||||
|
||||
cbox.setCurrentText(getattr(obj, prop))
|
||||
cbox.blockSignals(False)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -52,6 +52,3 @@ class _ExtractorTaskPanel(base_fempostpanel._BasePostTaskPanel):
|
||||
view.setWindowIcon(obj.ViewObject.Icon)
|
||||
|
||||
self.form = [app, view]
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@ class _TaskPanel(base_fempostpanel._BasePostTaskPanel):
|
||||
# form made from param and selection widget
|
||||
self.form = [self.widget, vobj.createDisplayTaskWidget()]
|
||||
|
||||
|
||||
# Setup functions
|
||||
# ###############
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ from femguiutils import vtk_table_view
|
||||
|
||||
translate = FreeCAD.Qt.translate
|
||||
|
||||
|
||||
class _TaskPanel(base_fempostpanel._BasePostTaskPanel):
|
||||
"""
|
||||
The TaskPanel for editing properties of glyph filter
|
||||
@@ -68,7 +69,6 @@ class _TaskPanel(base_fempostpanel._BasePostTaskPanel):
|
||||
self.data_widget.setWindowTitle(translate("FEM", "Histogram data"))
|
||||
self.data_widget.setWindowIcon(FreeCADGui.getIcon(":/icons/FEM_PostHistogram.svg"))
|
||||
|
||||
|
||||
# histogram parameter widget
|
||||
self.view_widget = FreeCADGui.PySideUic.loadUi(
|
||||
FreeCAD.getHomePath() + "Mod/Fem/Resources/ui/TaskPostHistogram.ui"
|
||||
@@ -81,7 +81,6 @@ class _TaskPanel(base_fempostpanel._BasePostTaskPanel):
|
||||
# form made from param and selection widget
|
||||
self.form = [self.data_widget, self.view_widget]
|
||||
|
||||
|
||||
# Setup functions
|
||||
# ###############
|
||||
|
||||
@@ -121,12 +120,13 @@ class _TaskPanel(base_fempostpanel._BasePostTaskPanel):
|
||||
self.view_widget.BarWidth.valueChanged.connect(self.barWidthChanged)
|
||||
self.view_widget.HatchWidth.valueChanged.connect(self.hatchWidthChanged)
|
||||
|
||||
|
||||
QtCore.Slot()
|
||||
|
||||
def showPlot(self):
|
||||
self.obj.ViewObject.Proxy.show_visualization()
|
||||
|
||||
QtCore.Slot()
|
||||
|
||||
def showTable(self):
|
||||
|
||||
# TODO: make data model update when object is recomputed
|
||||
@@ -137,49 +137,58 @@ class _TaskPanel(base_fempostpanel._BasePostTaskPanel):
|
||||
widget = vtk_table_view.VtkTableView(data_model)
|
||||
layout = QtGui.QVBoxLayout()
|
||||
layout.addWidget(widget)
|
||||
layout.setContentsMargins(0,0,0,0)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
dialog.setLayout(layout)
|
||||
dialog.resize(1500, 900)
|
||||
dialog.show()
|
||||
|
||||
|
||||
QtCore.Slot(int)
|
||||
|
||||
def binsChanged(self, bins):
|
||||
self.obj.ViewObject.Bins = bins
|
||||
|
||||
QtCore.Slot(int)
|
||||
|
||||
def typeChanged(self, idx):
|
||||
self.obj.ViewObject.Type = idx
|
||||
|
||||
QtCore.Slot(bool)
|
||||
|
||||
def comulativeChanged(self, state):
|
||||
self.obj.ViewObject.Cumulative = state
|
||||
|
||||
QtCore.Slot()
|
||||
|
||||
def titleChanged(self):
|
||||
self.obj.ViewObject.Title = self.view_widget.Title.text()
|
||||
|
||||
QtCore.Slot()
|
||||
|
||||
def xLabelChanged(self):
|
||||
self.obj.ViewObject.XLabel = self.view_widget.XLabel.text()
|
||||
|
||||
QtCore.Slot()
|
||||
|
||||
def yLabelChanged(self):
|
||||
self.obj.ViewObject.YLabel = self.view_widget.YLabel.text()
|
||||
|
||||
QtCore.Slot(int)
|
||||
|
||||
def legendPosChanged(self, idx):
|
||||
self.obj.ViewObject.LegendLocation = idx
|
||||
|
||||
QtCore.Slot(bool)
|
||||
|
||||
def legendShowChanged(self, state):
|
||||
self.obj.ViewObject.Legend = state
|
||||
|
||||
QtCore.Slot(float)
|
||||
|
||||
def barWidthChanged(self, value):
|
||||
self.obj.ViewObject.BarWidth = value
|
||||
|
||||
QtCore.Slot(float)
|
||||
|
||||
def hatchWidthChanged(self, value):
|
||||
self.obj.ViewObject.HatchLineWidth = value
|
||||
|
||||
@@ -40,6 +40,7 @@ from femguiutils import vtk_table_view
|
||||
|
||||
translate = FreeCAD.Qt.translate
|
||||
|
||||
|
||||
class _TaskPanel(base_fempostpanel._BasePostTaskPanel):
|
||||
"""
|
||||
The TaskPanel for editing properties of glyph filter
|
||||
@@ -68,7 +69,6 @@ class _TaskPanel(base_fempostpanel._BasePostTaskPanel):
|
||||
self.data_widget.setWindowTitle(translate("FEM", "Lineplot data"))
|
||||
self.data_widget.setWindowIcon(FreeCADGui.getIcon(":/icons/FEM_PostLineplot.svg"))
|
||||
|
||||
|
||||
# lineplot parameter widget
|
||||
self.view_widget = FreeCADGui.PySideUic.loadUi(
|
||||
FreeCAD.getHomePath() + "Mod/Fem/Resources/ui/TaskPostLineplot.ui"
|
||||
@@ -81,7 +81,6 @@ class _TaskPanel(base_fempostpanel._BasePostTaskPanel):
|
||||
# form made from param and selection widget
|
||||
self.form = [self.data_widget, self.view_widget]
|
||||
|
||||
|
||||
# Setup functions
|
||||
# ###############
|
||||
|
||||
@@ -104,7 +103,6 @@ class _TaskPanel(base_fempostpanel._BasePostTaskPanel):
|
||||
self.view_widget.LegendShow.setChecked(viewObj.Legend)
|
||||
self._enumPropertyToCombobox(viewObj, "LegendLocation", self.view_widget.LegendPos)
|
||||
|
||||
|
||||
# connect callbacks
|
||||
self.view_widget.Scale.activated.connect(self.scaleChanged)
|
||||
self.view_widget.Grid.toggled.connect(self.gridChanged)
|
||||
@@ -116,12 +114,13 @@ class _TaskPanel(base_fempostpanel._BasePostTaskPanel):
|
||||
self.view_widget.LegendShow.toggled.connect(self.legendShowChanged)
|
||||
self.view_widget.LegendPos.activated.connect(self.legendPosChanged)
|
||||
|
||||
|
||||
QtCore.Slot()
|
||||
|
||||
def showPlot(self):
|
||||
self.obj.ViewObject.Proxy.show_visualization()
|
||||
|
||||
QtCore.Slot()
|
||||
|
||||
def showTable(self):
|
||||
|
||||
# TODO: make data model update when object is recomputed
|
||||
@@ -132,37 +131,43 @@ class _TaskPanel(base_fempostpanel._BasePostTaskPanel):
|
||||
widget = vtk_table_view.VtkTableView(data_model)
|
||||
layout = QtGui.QVBoxLayout()
|
||||
layout.addWidget(widget)
|
||||
layout.setContentsMargins(0,0,0,0)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
dialog.setLayout(layout)
|
||||
dialog.resize(1500, 900)
|
||||
dialog.show()
|
||||
|
||||
|
||||
QtCore.Slot(int)
|
||||
|
||||
def scaleChanged(self, idx):
|
||||
self.obj.ViewObject.Scale = idx
|
||||
|
||||
QtCore.Slot(bool)
|
||||
|
||||
def gridChanged(self, state):
|
||||
self.obj.ViewObject.Grid = state
|
||||
|
||||
QtCore.Slot()
|
||||
|
||||
def titleChanged(self):
|
||||
self.obj.ViewObject.Title = self.view_widget.Title.text()
|
||||
|
||||
QtCore.Slot()
|
||||
|
||||
def xLabelChanged(self):
|
||||
self.obj.ViewObject.XLabel = self.view_widget.XLabel.text()
|
||||
|
||||
QtCore.Slot()
|
||||
|
||||
def yLabelChanged(self):
|
||||
self.obj.ViewObject.YLabel = self.view_widget.YLabel.text()
|
||||
|
||||
QtCore.Slot(int)
|
||||
|
||||
def legendPosChanged(self, idx):
|
||||
self.obj.ViewObject.LegendLocation = idx
|
||||
|
||||
QtCore.Slot(bool)
|
||||
|
||||
def legendShowChanged(self, state):
|
||||
self.obj.ViewObject.Legend = state
|
||||
|
||||
@@ -39,6 +39,7 @@ from femguiutils import extract_link_view as elv
|
||||
|
||||
translate = FreeCAD.Qt.translate
|
||||
|
||||
|
||||
class _TaskPanel(base_fempostpanel._BasePostTaskPanel):
|
||||
"""
|
||||
The TaskPanel for editing properties of glyph filter
|
||||
@@ -68,7 +69,6 @@ class _TaskPanel(base_fempostpanel._BasePostTaskPanel):
|
||||
# form made from param and selection widget
|
||||
self.form = [self.data_widget]
|
||||
|
||||
|
||||
# Setup functions
|
||||
# ###############
|
||||
|
||||
@@ -77,8 +77,6 @@ class _TaskPanel(base_fempostpanel._BasePostTaskPanel):
|
||||
# connect data widget
|
||||
self.data_widget.show_table.clicked.connect(self.showTable)
|
||||
|
||||
|
||||
@QtCore.Slot()
|
||||
def showTable(self):
|
||||
self.obj.ViewObject.Proxy.show_visualization()
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ from femobjects.base_fempythonobject import _PropHelper
|
||||
|
||||
False if FemGui.__name__ else True # flake8, dummy FemGui usage
|
||||
|
||||
|
||||
class _GuiPropHelper(_PropHelper):
|
||||
"""
|
||||
Helper class to manage property data inside proxy objects.
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
# ***************************************************************************
|
||||
# * Copyright (c) 2025 Stefan Tröger <stefantroeger@gmx.net> *
|
||||
# * *
|
||||
@@ -37,6 +36,7 @@ from PySide import QtGui
|
||||
|
||||
from femtaskpanels import task_post_extractor
|
||||
|
||||
|
||||
class VPPostExtractor:
|
||||
"""
|
||||
A View Provider for extraction of data
|
||||
@@ -74,18 +74,18 @@ class VPPostExtractor:
|
||||
if not group:
|
||||
return
|
||||
|
||||
if (hasattr(group.ViewObject, "Proxy") and
|
||||
hasattr(group.ViewObject.Proxy, "childViewPropertyChanged")):
|
||||
if hasattr(group.ViewObject, "Proxy") and hasattr(
|
||||
group.ViewObject.Proxy, "childViewPropertyChanged"
|
||||
):
|
||||
|
||||
group.ViewObject.Proxy.childViewPropertyChanged(vobj, prop)
|
||||
|
||||
|
||||
def setEdit(self, vobj, mode):
|
||||
|
||||
# build up the task panel
|
||||
taskd = task_post_extractor._ExtractorTaskPanel(vobj.Object)
|
||||
|
||||
#show it
|
||||
# show it
|
||||
FreeCADGui.Control.showDialog(taskd)
|
||||
|
||||
return True
|
||||
@@ -112,7 +112,6 @@ class VPPostExtractor:
|
||||
def loads(self, state):
|
||||
return None
|
||||
|
||||
|
||||
# To be implemented by subclasses:
|
||||
# ################################
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ __url__ = "https://www.freecad.org"
|
||||
import FreeCAD
|
||||
import FreeCADGui
|
||||
|
||||
|
||||
class VPPostVisualization:
|
||||
"""
|
||||
A View Provider for visualization objects
|
||||
@@ -42,23 +43,19 @@ class VPPostVisualization:
|
||||
self._setup_properties(vobj)
|
||||
vobj.addExtension("Gui::ViewProviderGroupExtensionPython")
|
||||
|
||||
|
||||
def _setup_properties(self, vobj):
|
||||
pl = vobj.PropertiesList
|
||||
for prop in self._get_properties():
|
||||
if not prop.name in pl:
|
||||
prop.add_to_object(vobj)
|
||||
|
||||
|
||||
def _get_properties(self):
|
||||
return []
|
||||
|
||||
|
||||
def attach(self, vobj):
|
||||
self.Object = vobj.Object
|
||||
self.ViewObject = vobj
|
||||
|
||||
|
||||
def isShow(self):
|
||||
# Mark ourself as visible in the tree
|
||||
return True
|
||||
@@ -66,7 +63,7 @@ class VPPostVisualization:
|
||||
def getDisplayModes(self, obj):
|
||||
return ["Dialog"]
|
||||
|
||||
def doubleClicked(self,vobj):
|
||||
def doubleClicked(self, vobj):
|
||||
|
||||
guidoc = FreeCADGui.getDocument(vobj.Object.Document)
|
||||
|
||||
@@ -107,7 +104,6 @@ class VPPostVisualization:
|
||||
def loads(self, state):
|
||||
return None
|
||||
|
||||
|
||||
# To be implemented by subclasses:
|
||||
# ################################
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ from . import view_base_fempostvisualization
|
||||
from femtaskpanels import task_post_histogram
|
||||
|
||||
from . import view_base_femobject
|
||||
|
||||
_GuiPropHelper = view_base_femobject._GuiPropHelper
|
||||
|
||||
|
||||
@@ -92,12 +93,11 @@ class EditViewWidget(QtGui.QWidget):
|
||||
self.widget.HatchDensity.setMaximumHeight(self.widget.Hatch.sizeHint().height())
|
||||
self.widget.LineWidth.setMaximumHeight(self.widget.LineStyle.sizeHint().height())
|
||||
|
||||
|
||||
def _setup_color_button(self, button, fcColor, callback):
|
||||
|
||||
barColor = QtGui.QColor(*[v*255 for v in fcColor])
|
||||
barColor = QtGui.QColor(*[v * 255 for v in fcColor])
|
||||
icon_size = button.iconSize()
|
||||
icon_size.setWidth(icon_size.width()*2)
|
||||
icon_size.setWidth(icon_size.width() * 2)
|
||||
button.setIconSize(icon_size)
|
||||
pixmap = QtGui.QPixmap(icon_size)
|
||||
pixmap.fill(barColor)
|
||||
@@ -114,7 +114,6 @@ class EditViewWidget(QtGui.QWidget):
|
||||
button.addAction(action)
|
||||
button.setPopupMode(QtGui.QToolButton.InstantPopup)
|
||||
|
||||
|
||||
@QtCore.Slot(QtGui.QColor)
|
||||
def lineColorChanged(self, color):
|
||||
|
||||
@@ -199,6 +198,7 @@ class EditFieldAppWidget(QtGui.QWidget):
|
||||
self._object.ExtractFrames = extract
|
||||
self._post_dialog._recompute()
|
||||
|
||||
|
||||
class EditIndexAppWidget(QtGui.QWidget):
|
||||
|
||||
def __init__(self, obj, post_dialog):
|
||||
@@ -279,7 +279,7 @@ class VPPostHistogramFieldData(view_base_fempostextractors.VPPostExtractor):
|
||||
name="Hatch",
|
||||
group="HistogramBar",
|
||||
doc=QT_TRANSLATE_NOOP("FEM", "The hatch pattern drawn in the bar"),
|
||||
value=['None', '/', '\\', '|', '-', '+', 'x', 'o', 'O', '.', '*'],
|
||||
value=["None", "/", "\\", "|", "-", "+", "x", "o", "O", ".", "*"],
|
||||
),
|
||||
_GuiPropHelper(
|
||||
type="App::PropertyIntegerConstraint",
|
||||
@@ -293,13 +293,15 @@ class VPPostHistogramFieldData(view_base_fempostextractors.VPPostExtractor):
|
||||
name="LineColor",
|
||||
group="HistogramLine",
|
||||
doc=QT_TRANSLATE_NOOP("FEM", "The color the data bin area is drawn with"),
|
||||
value=(0, 0, 0, 1), # black
|
||||
value=(0, 0, 0, 1), # black
|
||||
),
|
||||
_GuiPropHelper(
|
||||
type="App::PropertyFloatConstraint",
|
||||
name="LineWidth",
|
||||
group="HistogramLine",
|
||||
doc=QT_TRANSLATE_NOOP("FEM", "The width of the bar, between 0 and 1 (1 being without gaps)"),
|
||||
doc=QT_TRANSLATE_NOOP(
|
||||
"FEM", "The width of the bar, between 0 and 1 (1 being without gaps)"
|
||||
),
|
||||
value=(1, 0, 99, 0.1),
|
||||
),
|
||||
_GuiPropHelper(
|
||||
@@ -307,7 +309,7 @@ class VPPostHistogramFieldData(view_base_fempostextractors.VPPostExtractor):
|
||||
name="LineStyle",
|
||||
group="HistogramLine",
|
||||
doc=QT_TRANSLATE_NOOP("FEM", "The style the line is drawn in"),
|
||||
value=['None', '-', '--', '-.', ':'],
|
||||
value=["None", "-", "--", "-.", ":"],
|
||||
),
|
||||
]
|
||||
return super()._get_properties() + prop
|
||||
@@ -327,13 +329,13 @@ class VPPostHistogramFieldData(view_base_fempostextractors.VPPostExtractor):
|
||||
|
||||
def get_preview(self):
|
||||
|
||||
fig = mpl.pyplot.figure(figsize=(0.4,0.2), dpi=500)
|
||||
ax = mpl.pyplot.Axes(fig, [0., 0., 2, 1])
|
||||
fig = mpl.pyplot.figure(figsize=(0.4, 0.2), dpi=500)
|
||||
ax = mpl.pyplot.Axes(fig, [0.0, 0.0, 2, 1])
|
||||
ax.set_axis_off()
|
||||
fig.add_axes(ax)
|
||||
|
||||
kwargs = self.get_kw_args()
|
||||
patch = mpl.patches.Rectangle(xy=(0,0), width=2, height=1, **kwargs)
|
||||
patch = mpl.patches.Rectangle(xy=(0, 0), width=2, height=1, **kwargs)
|
||||
ax.add_patch(patch)
|
||||
|
||||
data = io.BytesIO()
|
||||
@@ -355,7 +357,7 @@ class VPPostHistogramFieldData(view_base_fempostextractors.VPPostExtractor):
|
||||
kwargs["linestyle"] = self.ViewObject.LineStyle
|
||||
kwargs["linewidth"] = self.ViewObject.LineWidth
|
||||
if self.ViewObject.Hatch != "None":
|
||||
kwargs["hatch"] = self.ViewObject.Hatch*self.ViewObject.HatchDensity
|
||||
kwargs["hatch"] = self.ViewObject.Hatch * self.ViewObject.HatchDensity
|
||||
|
||||
return kwargs
|
||||
|
||||
@@ -386,7 +388,6 @@ class VPPostHistogram(view_base_fempostvisualization.VPPostVisualization):
|
||||
def __init__(self, vobj):
|
||||
super().__init__(vobj)
|
||||
|
||||
|
||||
def _get_properties(self):
|
||||
|
||||
prop = [
|
||||
@@ -394,7 +395,9 @@ class VPPostHistogram(view_base_fempostvisualization.VPPostVisualization):
|
||||
type="App::PropertyBool",
|
||||
name="Cumulative",
|
||||
group="Histogram",
|
||||
doc=QT_TRANSLATE_NOOP("FEM", "If be the bars shoud show the cumulative sum left to rigth"),
|
||||
doc=QT_TRANSLATE_NOOP(
|
||||
"FEM", "If be the bars shoud show the cumulative sum left to rigth"
|
||||
),
|
||||
value=False,
|
||||
),
|
||||
_GuiPropHelper(
|
||||
@@ -402,13 +405,15 @@ class VPPostHistogram(view_base_fempostvisualization.VPPostVisualization):
|
||||
name="Type",
|
||||
group="Histogram",
|
||||
doc=QT_TRANSLATE_NOOP("FEM", "The type of histogram plotted"),
|
||||
value=["bar","barstacked", "step", "stepfilled"],
|
||||
value=["bar", "barstacked", "step", "stepfilled"],
|
||||
),
|
||||
_GuiPropHelper(
|
||||
type="App::PropertyFloatConstraint",
|
||||
name="BarWidth",
|
||||
group="Histogram",
|
||||
doc=QT_TRANSLATE_NOOP("FEM", "The width of the bar, between 0 and 1 (1 being without gaps)"),
|
||||
doc=QT_TRANSLATE_NOOP(
|
||||
"FEM", "The width of the bar, between 0 and 1 (1 being without gaps)"
|
||||
),
|
||||
value=(0.9, 0, 1, 0.05),
|
||||
),
|
||||
_GuiPropHelper(
|
||||
@@ -458,29 +463,36 @@ class VPPostHistogram(view_base_fempostvisualization.VPPostVisualization):
|
||||
name="LegendLocation",
|
||||
group="Plot",
|
||||
doc=QT_TRANSLATE_NOOP("FEM", "Determines if the legend is plotted"),
|
||||
value=['best','upper right','upper left','lower left','lower right','right',
|
||||
'center left','center right','lower center','upper center','center'],
|
||||
value=[
|
||||
"best",
|
||||
"upper right",
|
||||
"upper left",
|
||||
"lower left",
|
||||
"lower right",
|
||||
"right",
|
||||
"center left",
|
||||
"center right",
|
||||
"lower center",
|
||||
"upper center",
|
||||
"center",
|
||||
],
|
||||
),
|
||||
|
||||
]
|
||||
return prop
|
||||
|
||||
|
||||
def getIcon(self):
|
||||
return ":/icons/FEM_PostHistogram.svg"
|
||||
|
||||
|
||||
def setEdit(self, vobj, mode):
|
||||
|
||||
# build up the task panel
|
||||
taskd = task_post_histogram._TaskPanel(vobj)
|
||||
|
||||
#show it
|
||||
# show it
|
||||
FreeCADGui.Control.showDialog(taskd)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def show_visualization(self):
|
||||
|
||||
if not hasattr(self, "_plot") or not self._plot:
|
||||
@@ -489,12 +501,11 @@ class VPPostHistogram(view_base_fempostvisualization.VPPostVisualization):
|
||||
self._plot.setWindowTitle(self.Object.Label)
|
||||
self._plot.setParent(main)
|
||||
self._plot.setWindowFlags(QtGui.Qt.Dialog)
|
||||
self._plot.resize(main.size().height()/2, main.size().height()/3) # keep it square
|
||||
self._plot.resize(main.size().height() / 2, main.size().height() / 3) # keep it square
|
||||
self.update_visualization()
|
||||
|
||||
self._plot.show()
|
||||
|
||||
|
||||
def get_kw_args(self, obj):
|
||||
view = obj.ViewObject
|
||||
if not view or not hasattr(view, "Proxy"):
|
||||
@@ -503,7 +514,6 @@ class VPPostHistogram(view_base_fempostvisualization.VPPostVisualization):
|
||||
return {}
|
||||
return view.Proxy.get_kw_args()
|
||||
|
||||
|
||||
def update_visualization(self):
|
||||
|
||||
if not hasattr(self, "_plot") or not self._plot:
|
||||
@@ -523,7 +533,7 @@ class VPPostHistogram(view_base_fempostvisualization.VPPostVisualization):
|
||||
kwargs = self.get_kw_args(child)
|
||||
|
||||
# iterate over the table and plot all
|
||||
color_factor = np.linspace(1,0.5,table.GetNumberOfColumns())
|
||||
color_factor = np.linspace(1, 0.5, table.GetNumberOfColumns())
|
||||
legend_multiframe = table.GetNumberOfColumns() > 1
|
||||
for i in range(table.GetNumberOfColumns()):
|
||||
|
||||
@@ -532,7 +542,7 @@ class VPPostHistogram(view_base_fempostvisualization.VPPostVisualization):
|
||||
for key in kwargs:
|
||||
|
||||
if "color" in key:
|
||||
value = np.array(kwargs[key])*color_factor[i]
|
||||
value = np.array(kwargs[key]) * color_factor[i]
|
||||
args[key] = mpl.colors.to_hex(value)
|
||||
|
||||
full_args.append(args)
|
||||
@@ -581,7 +591,7 @@ class VPPostHistogram(view_base_fempostvisualization.VPPostVisualization):
|
||||
self._plot.axes.set_ylabel(self.ViewObject.YLabel)
|
||||
|
||||
if self.ViewObject.Legend and labels:
|
||||
self._plot.axes.legend(loc = self.ViewObject.LegendLocation)
|
||||
self._plot.axes.legend(loc=self.ViewObject.LegendLocation)
|
||||
|
||||
self._plot.update()
|
||||
|
||||
|
||||
@@ -48,8 +48,10 @@ from . import view_base_fempostvisualization
|
||||
from femtaskpanels import task_post_lineplot
|
||||
|
||||
from . import view_base_femobject
|
||||
|
||||
_GuiPropHelper = view_base_femobject._GuiPropHelper
|
||||
|
||||
|
||||
class EditViewWidget(QtGui.QWidget):
|
||||
|
||||
def __init__(self, obj, post_dialog):
|
||||
@@ -91,9 +93,9 @@ class EditViewWidget(QtGui.QWidget):
|
||||
|
||||
def _setup_color_button(self, button, fcColor, callback):
|
||||
|
||||
barColor = QtGui.QColor(*[v*255 for v in fcColor])
|
||||
barColor = QtGui.QColor(*[v * 255 for v in fcColor])
|
||||
icon_size = button.iconSize()
|
||||
icon_size.setWidth(icon_size.width()*2)
|
||||
icon_size.setWidth(icon_size.width() * 2)
|
||||
button.setIconSize(icon_size)
|
||||
pixmap = QtGui.QPixmap(icon_size)
|
||||
pixmap.fill(barColor)
|
||||
@@ -110,7 +112,6 @@ class EditViewWidget(QtGui.QWidget):
|
||||
button.addAction(action)
|
||||
button.setPopupMode(QtGui.QToolButton.InstantPopup)
|
||||
|
||||
|
||||
@QtCore.Slot(QtGui.QColor)
|
||||
def colorChanged(self, color):
|
||||
|
||||
@@ -163,9 +164,13 @@ class EditFieldAppWidget(QtGui.QWidget):
|
||||
# set the other properties
|
||||
|
||||
self._post_dialog._enumPropertyToCombobox(self._object, "XField", self.widget.XField)
|
||||
self._post_dialog._enumPropertyToCombobox(self._object, "XComponent", self.widget.XComponent)
|
||||
self._post_dialog._enumPropertyToCombobox(
|
||||
self._object, "XComponent", self.widget.XComponent
|
||||
)
|
||||
self._post_dialog._enumPropertyToCombobox(self._object, "YField", self.widget.YField)
|
||||
self._post_dialog._enumPropertyToCombobox(self._object, "YComponent", self.widget.YComponent)
|
||||
self._post_dialog._enumPropertyToCombobox(
|
||||
self._object, "YComponent", self.widget.YComponent
|
||||
)
|
||||
self.widget.Extract.setChecked(self._object.ExtractFrames)
|
||||
|
||||
self.widget.XField.activated.connect(self.xFieldChanged)
|
||||
@@ -177,7 +182,9 @@ class EditFieldAppWidget(QtGui.QWidget):
|
||||
@QtCore.Slot(int)
|
||||
def xFieldChanged(self, index):
|
||||
self._object.XField = index
|
||||
self._post_dialog._enumPropertyToCombobox(self._object, "XComponent", self.widget.XComponent)
|
||||
self._post_dialog._enumPropertyToCombobox(
|
||||
self._object, "XComponent", self.widget.XComponent
|
||||
)
|
||||
self._post_dialog._recompute()
|
||||
|
||||
@QtCore.Slot(int)
|
||||
@@ -188,7 +195,9 @@ class EditFieldAppWidget(QtGui.QWidget):
|
||||
@QtCore.Slot(int)
|
||||
def yFieldChanged(self, index):
|
||||
self._object.YField = index
|
||||
self._post_dialog._enumPropertyToCombobox(self._object, "YComponent", self.widget.YComponent)
|
||||
self._post_dialog._enumPropertyToCombobox(
|
||||
self._object, "YComponent", self.widget.YComponent
|
||||
)
|
||||
self._post_dialog._recompute()
|
||||
|
||||
@QtCore.Slot(int)
|
||||
@@ -225,7 +234,9 @@ class EditIndexAppWidget(QtGui.QWidget):
|
||||
|
||||
self.widget.Index.setValue(self._object.Index)
|
||||
self._post_dialog._enumPropertyToCombobox(self._object, "YField", self.widget.YField)
|
||||
self._post_dialog._enumPropertyToCombobox(self._object, "YComponent", self.widget.YComponent)
|
||||
self._post_dialog._enumPropertyToCombobox(
|
||||
self._object, "YComponent", self.widget.YComponent
|
||||
)
|
||||
|
||||
self.widget.Index.valueChanged.connect(self.indexChanged)
|
||||
self.widget.YField.activated.connect(self.yFieldChanged)
|
||||
@@ -242,7 +253,9 @@ class EditIndexAppWidget(QtGui.QWidget):
|
||||
@QtCore.Slot(int)
|
||||
def yFieldChanged(self, index):
|
||||
self._object.YField = index
|
||||
self._post_dialog._enumPropertyToCombobox(self._object, "YComponent", self.widget.YComponent)
|
||||
self._post_dialog._enumPropertyToCombobox(
|
||||
self._object, "YComponent", self.widget.YComponent
|
||||
)
|
||||
self._post_dialog._recompute()
|
||||
|
||||
@QtCore.Slot(int)
|
||||
@@ -282,7 +295,7 @@ class VPPostLineplotFieldData(view_base_fempostextractors.VPPostExtractor):
|
||||
name="LineStyle",
|
||||
group="Lineplot",
|
||||
doc=QT_TRANSLATE_NOOP("FEM", "The style the line is drawn in"),
|
||||
value=['-', '--', '-.', ':', 'None'],
|
||||
value=["-", "--", "-.", ":", "None"],
|
||||
),
|
||||
_GuiPropHelper(
|
||||
type="App::PropertyFloatConstraint",
|
||||
@@ -296,7 +309,7 @@ class VPPostLineplotFieldData(view_base_fempostextractors.VPPostExtractor):
|
||||
name="MarkerStyle",
|
||||
group="Lineplot",
|
||||
doc=QT_TRANSLATE_NOOP("FEM", "The style the data markers are drawn with"),
|
||||
value=['None', '*', '+', 's', '.', 'o', 'x'],
|
||||
value=["None", "*", "+", "s", ".", "o", "x"],
|
||||
),
|
||||
_GuiPropHelper(
|
||||
type="App::PropertyFloatConstraint",
|
||||
@@ -325,13 +338,13 @@ class VPPostLineplotFieldData(view_base_fempostextractors.VPPostExtractor):
|
||||
# Returns the preview tuple of icon and label: (QPixmap, str)
|
||||
# Note: QPixmap in ratio 2:1
|
||||
|
||||
fig = mpl.pyplot.figure(figsize=(0.2,0.1), dpi=1000)
|
||||
ax = mpl.pyplot.Axes(fig, [0., 0., 1., 1.])
|
||||
fig = mpl.pyplot.figure(figsize=(0.2, 0.1), dpi=1000)
|
||||
ax = mpl.pyplot.Axes(fig, [0.0, 0.0, 1.0, 1.0])
|
||||
ax.set_axis_off()
|
||||
fig.add_axes(ax)
|
||||
kwargs = self.get_kw_args()
|
||||
kwargs["markevery"] = [1]
|
||||
ax.plot([0,0.5,1],[0.5,0.5,0.5], **kwargs)
|
||||
ax.plot([0, 0.5, 1], [0.5, 0.5, 0.5], **kwargs)
|
||||
data = io.BytesIO()
|
||||
mpl.pyplot.savefig(data, bbox_inches=0, transparent=True)
|
||||
mpl.pyplot.close()
|
||||
@@ -341,7 +354,6 @@ class VPPostLineplotFieldData(view_base_fempostextractors.VPPostExtractor):
|
||||
|
||||
return (pixmap, self.ViewObject.Legend)
|
||||
|
||||
|
||||
def get_kw_args(self):
|
||||
# builds kw args from the properties
|
||||
kwargs = {}
|
||||
@@ -383,7 +395,6 @@ class VPPostLineplot(view_base_fempostvisualization.VPPostVisualization):
|
||||
def __init__(self, vobj):
|
||||
super().__init__(vobj)
|
||||
|
||||
|
||||
def _get_properties(self):
|
||||
|
||||
prop = [
|
||||
@@ -391,7 +402,9 @@ class VPPostLineplot(view_base_fempostvisualization.VPPostVisualization):
|
||||
type="App::PropertyBool",
|
||||
name="Grid",
|
||||
group="Lineplot",
|
||||
doc=QT_TRANSLATE_NOOP("FEM", "If be the bars shoud show the cumulative sum left to rigth"),
|
||||
doc=QT_TRANSLATE_NOOP(
|
||||
"FEM", "If be the bars shoud show the cumulative sum left to rigth"
|
||||
),
|
||||
value=True,
|
||||
),
|
||||
_GuiPropHelper(
|
||||
@@ -399,9 +412,9 @@ class VPPostLineplot(view_base_fempostvisualization.VPPostVisualization):
|
||||
name="Scale",
|
||||
group="Lineplot",
|
||||
doc=QT_TRANSLATE_NOOP("FEM", "The scale the axis are drawn in"),
|
||||
value=["linear","semi-log x", "semi-log y", "log"],
|
||||
value=["linear", "semi-log x", "semi-log y", "log"],
|
||||
),
|
||||
_GuiPropHelper(
|
||||
_GuiPropHelper(
|
||||
type="App::PropertyString",
|
||||
name="Title",
|
||||
group="Plot",
|
||||
@@ -434,29 +447,36 @@ class VPPostLineplot(view_base_fempostvisualization.VPPostVisualization):
|
||||
name="LegendLocation",
|
||||
group="Plot",
|
||||
doc=QT_TRANSLATE_NOOP("FEM", "Determines if the legend is plotted"),
|
||||
value=['best','upper right','upper left','lower left','lower right','right',
|
||||
'center left','center right','lower center','upper center','center'],
|
||||
value=[
|
||||
"best",
|
||||
"upper right",
|
||||
"upper left",
|
||||
"lower left",
|
||||
"lower right",
|
||||
"right",
|
||||
"center left",
|
||||
"center right",
|
||||
"lower center",
|
||||
"upper center",
|
||||
"center",
|
||||
],
|
||||
),
|
||||
|
||||
]
|
||||
return prop
|
||||
|
||||
|
||||
def getIcon(self):
|
||||
return ":/icons/FEM_PostLineplot.svg"
|
||||
|
||||
|
||||
def setEdit(self, vobj, mode):
|
||||
|
||||
# build up the task panel
|
||||
taskd = task_post_lineplot._TaskPanel(vobj)
|
||||
|
||||
#show it
|
||||
# show it
|
||||
FreeCADGui.Control.showDialog(taskd)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def show_visualization(self):
|
||||
|
||||
if not hasattr(self, "_plot") or not self._plot:
|
||||
@@ -465,12 +485,13 @@ class VPPostLineplot(view_base_fempostvisualization.VPPostVisualization):
|
||||
self._plot.setWindowTitle(self.Object.Label)
|
||||
self._plot.setParent(main)
|
||||
self._plot.setWindowFlags(QtGui.Qt.Dialog)
|
||||
self._plot.resize(main.size().height()/2, main.size().height()/3) # keep the aspect ratio
|
||||
self._plot.resize(
|
||||
main.size().height() / 2, main.size().height() / 3
|
||||
) # keep the aspect ratio
|
||||
self.update_visualization()
|
||||
|
||||
self._plot.show()
|
||||
|
||||
|
||||
def get_kw_args(self, obj):
|
||||
view = obj.ViewObject
|
||||
if not view or not hasattr(view, "Proxy"):
|
||||
@@ -479,7 +500,6 @@ class VPPostLineplot(view_base_fempostvisualization.VPPostVisualization):
|
||||
return {}
|
||||
return view.Proxy.get_kw_args()
|
||||
|
||||
|
||||
def update_visualization(self):
|
||||
|
||||
if not hasattr(self, "_plot") or not self._plot:
|
||||
@@ -496,10 +516,10 @@ class VPPostLineplot(view_base_fempostvisualization.VPPostVisualization):
|
||||
kwargs = self.get_kw_args(child)
|
||||
|
||||
# iterate over the table and plot all (note: column 0 is always X!)
|
||||
color_factor = np.linspace(1,0.5,int(table.GetNumberOfColumns()/2))
|
||||
color_factor = np.linspace(1, 0.5, int(table.GetNumberOfColumns() / 2))
|
||||
legend_multiframe = table.GetNumberOfColumns() > 2
|
||||
|
||||
for i in range(0,table.GetNumberOfColumns(),2):
|
||||
for i in range(0, table.GetNumberOfColumns(), 2):
|
||||
|
||||
plotted = True
|
||||
|
||||
@@ -507,13 +527,13 @@ class VPPostLineplot(view_base_fempostvisualization.VPPostVisualization):
|
||||
tmp_args = {}
|
||||
for key in kwargs:
|
||||
if "color" in key:
|
||||
value = np.array(kwargs[key])*color_factor[int(i/2)]
|
||||
value = np.array(kwargs[key]) * color_factor[int(i / 2)]
|
||||
tmp_args[key] = mpl.colors.to_hex(value)
|
||||
else:
|
||||
tmp_args[key] = kwargs[key]
|
||||
|
||||
xdata = VTKArray(table.GetColumn(i))
|
||||
ydata = VTKArray(table.GetColumn(i+1))
|
||||
ydata = VTKArray(table.GetColumn(i + 1))
|
||||
|
||||
# ensure points are visible if it is a single datapoint
|
||||
if len(xdata) == 1 and tmp_args["marker"] == "None":
|
||||
@@ -524,13 +544,13 @@ class VPPostLineplot(view_base_fempostvisualization.VPPostVisualization):
|
||||
if not legend_multiframe:
|
||||
label = child.ViewObject.Legend
|
||||
else:
|
||||
postfix = table.GetColumnName(i+1).split("-")[-1]
|
||||
postfix = table.GetColumnName(i + 1).split("-")[-1]
|
||||
label = child.ViewObject.Legend + " - " + postfix
|
||||
else:
|
||||
legend_prefix = ""
|
||||
if len(self.Object.Group) > 1:
|
||||
legend_prefix = child.Source.Label + ": "
|
||||
label = legend_prefix + table.GetColumnName(i+1)
|
||||
label = legend_prefix + table.GetColumnName(i + 1)
|
||||
|
||||
match self.ViewObject.Scale:
|
||||
case "log":
|
||||
@@ -550,7 +570,7 @@ class VPPostLineplot(view_base_fempostvisualization.VPPostVisualization):
|
||||
self._plot.axes.set_ylabel(self.ViewObject.YLabel)
|
||||
|
||||
if self.ViewObject.Legend and plotted:
|
||||
self._plot.axes.legend(loc = self.ViewObject.LegendLocation)
|
||||
self._plot.axes.legend(loc=self.ViewObject.LegendLocation)
|
||||
|
||||
self._plot.axes.grid(self.ViewObject.Grid)
|
||||
self._plot.update()
|
||||
@@ -561,4 +581,3 @@ class VPPostLineplot(view_base_fempostvisualization.VPPostVisualization):
|
||||
i = len(self.Object.Group)
|
||||
cmap = mpl.pyplot.get_cmap("tab10")
|
||||
return cmap(i)
|
||||
|
||||
|
||||
@@ -41,8 +41,10 @@ from femtaskpanels import task_post_table
|
||||
from femguiutils import vtk_table_view as vtv
|
||||
|
||||
from . import view_base_femobject
|
||||
|
||||
_GuiPropHelper = view_base_femobject._GuiPropHelper
|
||||
|
||||
|
||||
class EditViewWidget(QtGui.QWidget):
|
||||
|
||||
def __init__(self, obj, post_dialog):
|
||||
@@ -116,6 +118,7 @@ class EditFieldAppWidget(QtGui.QWidget):
|
||||
self._object.ExtractFrames = extract
|
||||
self._post_dialog._recompute()
|
||||
|
||||
|
||||
class EditIndexAppWidget(QtGui.QWidget):
|
||||
|
||||
def __init__(self, obj, post_dialog):
|
||||
@@ -180,7 +183,9 @@ class VPPostTableFieldData(view_base_fempostextractors.VPPostExtractor):
|
||||
type="App::PropertyString",
|
||||
name="Name",
|
||||
group="Table",
|
||||
doc=QT_TRANSLATE_NOOP("FEM", "The name used in the table header. Default name is used if empty"),
|
||||
doc=QT_TRANSLATE_NOOP(
|
||||
"FEM", "The name used in the table header. Default name is used if empty"
|
||||
),
|
||||
value="",
|
||||
),
|
||||
]
|
||||
@@ -232,22 +237,19 @@ class VPPostTable(view_base_fempostvisualization.VPPostVisualization):
|
||||
def __init__(self, vobj):
|
||||
super().__init__(vobj)
|
||||
|
||||
|
||||
def getIcon(self):
|
||||
return ":/icons/FEM_PostSpreadsheet.svg"
|
||||
|
||||
|
||||
def setEdit(self, vobj, mode):
|
||||
|
||||
# build up the task panel
|
||||
taskd = task_post_table._TaskPanel(vobj)
|
||||
|
||||
#show it
|
||||
# show it
|
||||
FreeCADGui.Control.showDialog(taskd)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def show_visualization(self):
|
||||
|
||||
if not hasattr(self, "_tableview") or not self._tableview:
|
||||
@@ -257,13 +259,14 @@ class VPPostTable(view_base_fempostvisualization.VPPostVisualization):
|
||||
self._tableview.setWindowTitle(self.Object.Label)
|
||||
self._tableview.setParent(main)
|
||||
self._tableview.setWindowFlags(QtGui.Qt.Dialog)
|
||||
self._tableview.resize(main.size().height()/2, main.size().height()/3) # keep the aspect ratio
|
||||
self._tableview.resize(
|
||||
main.size().height() / 2, main.size().height() / 3
|
||||
) # keep the aspect ratio
|
||||
|
||||
self.update_visualization()
|
||||
|
||||
self._tableview.show()
|
||||
|
||||
|
||||
def update_visualization(self):
|
||||
|
||||
if not hasattr(self, "_tableModel") or not self._tableModel:
|
||||
@@ -286,5 +289,3 @@ class VPPostTable(view_base_fempostvisualization.VPPostVisualization):
|
||||
header[table.GetColumnName(i)] = new_name
|
||||
|
||||
self._tableModel.setTable(self.Object.Table, header)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user