diff --git a/src/Mod/Fem/App/CMakeLists.txt b/src/Mod/Fem/App/CMakeLists.txt
index d27e6760df..551d956c23 100755
--- a/src/Mod/Fem/App/CMakeLists.txt
+++ b/src/Mod/Fem/App/CMakeLists.txt
@@ -92,6 +92,7 @@ SET(FemScripts_SRCS
_FemMaterial.py
_TaskPanelFemBeamSection.py
_TaskPanelFemMeshGmsh.py
+ _TaskPanelFemMeshGroup.py
_TaskPanelFemMeshRegion.py
_TaskPanelFemShellThickness.py
_TaskPanelFemSolverCalculix.py
@@ -140,6 +141,7 @@ SET(FemScripts_SRCS
z88DispReader.py
TaskPanelFemBeamSection.ui
TaskPanelFemMeshGmsh.ui
+ TaskPanelFemMeshGroup.ui
TaskPanelFemMeshRegion.ui
TaskPanelFemShellThickness.ui
TaskPanelFemSolverCalculix.ui
diff --git a/src/Mod/Fem/CMakeLists.txt b/src/Mod/Fem/CMakeLists.txt
index 3324b2e53f..308e3d580d 100755
--- a/src/Mod/Fem/CMakeLists.txt
+++ b/src/Mod/Fem/CMakeLists.txt
@@ -59,6 +59,8 @@ INSTALL(
_FemMeshGroup.py
_ViewProviderFemMeshGroup.py
_CommandMeshGroup.py
+ _TaskPanelFemMeshGroup.py
+ TaskPanelFemMeshGroup.ui
FemMeshRegion.py
_FemMeshRegion.py
diff --git a/src/Mod/Fem/TaskPanelFemMeshGroup.ui b/src/Mod/Fem/TaskPanelFemMeshGroup.ui
new file mode 100644
index 0000000000..6a7cf9bb90
--- /dev/null
+++ b/src/Mod/Fem/TaskPanelFemMeshGroup.ui
@@ -0,0 +1,120 @@
+
+
+ Form
+
+
+
+ 0
+ 0
+ 350
+ 500
+
+
+
+ Mesh group
+
+
+ -
+
+
+
+ 16777215
+ 1677215
+
+
+
+ Identifier used for mesh export
+
+
+
-
+
+
+ QFormLayout::AllNonFixedFieldsGrow
+
+
-
+
+
+ Name
+
+
+ true
+
+
+
+ -
+
+
+ Label
+
+
+
+
+
+
+
+
+ -
+
+
+ References
+
+
+
-
+
+
+ Add reference
+
+
+
+ -
+
+
+ -
+
+
-
+
+
+ Solid
+
+
+
+ -
+
+
+ Face, Edge, Vertex
+
+
+ true
+
+
+
+ -
+
+
+ <html><head/><body><p>Selection</p></body></html>
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
diff --git a/src/Mod/Fem/_TaskPanelFemMeshGroup.py b/src/Mod/Fem/_TaskPanelFemMeshGroup.py
new file mode 100644
index 0000000000..018d882a35
--- /dev/null
+++ b/src/Mod/Fem/_TaskPanelFemMeshGroup.py
@@ -0,0 +1,190 @@
+# ***************************************************************************
+# * *
+# * Copyright (c) 2016 - Bernd Hahnebach *
+# * *
+# * This program is free software; you can redistribute it and/or modify *
+# * it under the terms of the GNU Lesser General Public License (LGPL) *
+# * as published by the Free Software Foundation; either version 2 of *
+# * the License, or (at your option) any later version. *
+# * for detail see the LICENCE text file. *
+# * *
+# * This program is distributed in the hope that it will be useful, *
+# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+# * GNU Library General Public License for more details. *
+# * *
+# * You should have received a copy of the GNU Library General Public *
+# * License along with this program; if not, write to the Free Software *
+# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
+# * USA *
+# * *
+# ***************************************************************************
+
+__title__ = "_TaskPanelFemMeshGroup"
+__author__ = "Bernd Hahnebach"
+__url__ = "http://www.freecadweb.org"
+
+## @package TaskPanelFemMeshGroup
+# \ingroup FEM
+
+import FreeCAD
+import FreeCADGui
+from PySide import QtGui
+from PySide import QtCore
+
+
+class _TaskPanelFemMeshGroup:
+ '''The TaskPanel for editing References property of FemMeshGroup objects'''
+ def __init__(self, obj):
+ FreeCADGui.Selection.clearSelection()
+ self.sel_server = None
+ self.obj = obj
+ self.selection_mode_solid = False
+ self.selection_mode_std_print_message = "Select Faces, Edges and Vertices by single click on them to add them to the list."
+ self.selection_mode_solid_print_message = "Select Solids by single click on a Face or Edge which belongs to the Solid, to add the Solid to the list."
+
+ self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/TaskPanelFemMeshGroup.ui")
+ QtCore.QObject.connect(self.form.rb_name, QtCore.SIGNAL("toggled(bool)"), self.choose_exportidentifier_name)
+ QtCore.QObject.connect(self.form.rb_label, QtCore.SIGNAL("toggled(bool)"), self.choose_exportidentifier_label)
+ QtCore.QObject.connect(self.form.rb_standard, QtCore.SIGNAL("toggled(bool)"), self.choose_selection_mode_standard)
+ QtCore.QObject.connect(self.form.rb_solid, QtCore.SIGNAL("toggled(bool)"), self.choose_selection_mode_solid)
+ QtCore.QObject.connect(self.form.pushButton_Reference, QtCore.SIGNAL("clicked()"), self.add_references)
+ self.form.list_References.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
+ self.form.list_References.connect(self.form.list_References, QtCore.SIGNAL("customContextMenuRequested(QPoint)"), self.references_list_right_clicked)
+
+ self.get_meshgroup_props()
+ self.update()
+
+ def accept(self):
+ self.set_meshgroup_props()
+ if self.sel_server:
+ FreeCADGui.Selection.removeObserver(self.sel_server)
+ FreeCADGui.ActiveDocument.resetEdit()
+ FreeCAD.ActiveDocument.recompute()
+ return True
+
+ def reject(self):
+ if self.sel_server:
+ FreeCADGui.Selection.removeObserver(self.sel_server)
+ FreeCADGui.ActiveDocument.resetEdit()
+ return True
+
+ def get_meshgroup_props(self):
+ self.use_label = self.obj.UseLabel
+ self.references = []
+ if self.obj.References:
+ self.tuplereferences = self.obj.References
+ self.get_references()
+
+ def set_meshgroup_props(self):
+ self.obj.References = self.references
+ self.obj.UseLabel = self.use_label
+
+ def update(self):
+ 'fills the widgets'
+ self.form.rb_name.setChecked(not self.use_label)
+ self.form.rb_label.setChecked(self.use_label)
+ self.rebuild_list_References()
+
+ def choose_exportidentifier_name(self, state):
+ self.use_label = not state
+
+ def choose_exportidentifier_label(self, state):
+ self.use_label = state
+
+ def choose_selection_mode_standard(self, state):
+ self.selection_mode_solid = not state
+ if self.sel_server and not self.selection_mode_solid:
+ print(self.selection_mode_std_print_message)
+
+ def choose_selection_mode_solid(self, state):
+ self.selection_mode_solid = state
+ if self.sel_server and self.selection_mode_solid:
+ print(self.selection_mode_solid_print_message)
+
+ def get_references(self):
+ for ref in self.tuplereferences:
+ for elem in ref[1]:
+ self.references.append((ref[0], elem))
+
+ def references_list_right_clicked(self, QPos):
+ self.form.contextMenu = QtGui.QMenu()
+ menu_item = self.form.contextMenu.addAction("Remove Reference")
+ if not self.references:
+ menu_item.setDisabled(True)
+ self.form.connect(menu_item, QtCore.SIGNAL("triggered()"), self.remove_reference)
+ parentPosition = self.form.list_References.mapToGlobal(QtCore.QPoint(0, 0))
+ self.form.contextMenu.move(parentPosition + QPos)
+ self.form.contextMenu.show()
+
+ def remove_reference(self):
+ if not self.references:
+ return
+ currentItemName = str(self.form.list_References.currentItem().text())
+ for ref in self.references:
+ refname_to_compare_listentry = ref[0].Name + ':' + ref[1]
+ if refname_to_compare_listentry == currentItemName:
+ self.references.remove(ref)
+ self.rebuild_list_References()
+
+ def add_references(self):
+ '''Called if Button add_reference is triggered'''
+ # in constraints EditTaskPanel the selection is active as soon as the taskpanel is open
+ # here the addReference button EditTaskPanel has to be triggered to start selection mode
+ FreeCADGui.Selection.clearSelection()
+ # start SelectionObserver and parse the function to add the References to the widget
+ if self.selection_mode_solid: # print message on button click
+ print_message = self.selection_mode_solid_print_message
+ else:
+ print_message = self.selection_mode_std_print_message
+ import FemSelectionObserver
+ self.sel_server = FemSelectionObserver.FemSelectionObserver(self.selectionParser, print_message)
+
+ def selectionParser(self, selection):
+ print('selection: ', selection[0].Shape.ShapeType, ' ', selection[0].Name, ' ', selection[1])
+ if hasattr(selection[0], "Shape") and selection[1]:
+ elt = selection[0].Shape.getElement(selection[1])
+ if self.selection_mode_solid:
+ # in solid selection mode use edges and faces for selection of a solid
+ solid_to_add = None
+ if elt.ShapeType == 'Edge':
+ found_edge = False
+ for i, s in enumerate(selection[0].Shape.Solids):
+ for e in s.Edges:
+ if elt.isSame(e):
+ if not found_edge:
+ solid_to_add = str(i + 1)
+ else:
+ FreeCAD.Console.PrintMessage('Edge belongs to more than one solid\n')
+ solid_to_add = None
+ found_edge = True
+ elif elt.ShapeType == 'Face':
+ found_face = False
+ for i, s in enumerate(selection[0].Shape.Solids):
+ for e in s.Faces:
+ if elt.isSame(e):
+ if not found_face:
+ solid_to_add = str(i + 1)
+ else:
+ FreeCAD.Console.PrintMessage('Face belongs to more than one solid\n')
+ solid_to_add = None
+ found_edge = True
+ if solid_to_add:
+ selection = (selection[0], 'Solid' + solid_to_add)
+ print('selection element changed to Solid: ', selection[0].Shape.ShapeType, ' ', selection[0].Name, ' ', selection[1])
+ else:
+ return
+ if selection not in self.references:
+ self.references.append(selection)
+ self.rebuild_list_References()
+ else:
+ FreeCAD.Console.PrintMessage(selection[0].Name + ' --> ' + selection[1] + ' is in reference list already!\n')
+
+ def rebuild_list_References(self):
+ self.form.list_References.clear()
+ items = []
+ for ref in self.references:
+ item_name = ref[0].Name + ':' + ref[1]
+ items.append(item_name)
+ for listItemName in sorted(items):
+ self.form.list_References.addItem(listItemName)