diff --git a/src/Mod/Fem/Gui/Resources/ui/ElementGeometry2D.ui b/src/Mod/Fem/Gui/Resources/ui/ElementGeometry2D.ui index 51ca0f45e4..e950588b09 100644 --- a/src/Mod/Fem/Gui/Resources/ui/ElementGeometry2D.ui +++ b/src/Mod/Fem/Gui/Resources/ui/ElementGeometry2D.ui @@ -83,32 +83,6 @@ - - - - References - - - - - - Leave blank to choose all remaining shapes - - - - - - - Add reference - - - - - - - - - diff --git a/src/Mod/Fem/femguiobjects/FemSelectionWidgets.py b/src/Mod/Fem/femguiobjects/FemSelectionWidgets.py index 0d87a0752c..3c02ff0484 100644 --- a/src/Mod/Fem/femguiobjects/FemSelectionWidgets.py +++ b/src/Mod/Fem/femguiobjects/FemSelectionWidgets.py @@ -1,6 +1,7 @@ # *************************************************************************** # * * # * Copyright (c) 2017 - Markus Hovorka * +# * Copyright (c) 2018 - 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) * @@ -22,10 +23,13 @@ __title__ = "FemSelectWidget" -__author__ = "Markus Hovorka" +__author__ = "Markus Hovorka, Bernd Hahnebach" __url__ = "http://www.freecadweb.org" +import FreeCAD +import FreeCADGui + from PySide import QtGui from PySide import QtCore @@ -202,3 +206,148 @@ class SmallListView(QtGui.QListView): def sizeHint(self): return QtCore.QSize(50, 50) + + +class FacesSelection(QtGui.QWidget): + + def __init__(self, ref): + super(FacesSelection, self).__init__() + # init ui stuff + FreeCADGui.Selection.clearSelection() + self.sel_server = None + self.obj_notvisible = [] + self.initUI() + # set references and fill the list widget + self.references = [] + if ref: + self.tuplereferences = ref + self.get_references() + self.rebuild_list_References() + + def initUI(self): + # auch ArchPanel ist coded ohne ui-file + # title + self.setWindowTitle(self.tr("Geometry reference selector")) + # button + self.pushButton_Add = QtGui.QPushButton(self.tr("Add")) + # label + self._helpTextLbl = QtGui.QLabel() + self._helpTextLbl.setWordWrap(True) + self._helpTextLbl.setText(self.tr( + "Click on \"Add\" and select Faces. Only adding of Faces is allowed." + " If no geometry is added to the list, all remaining ones are used.")) + # list + self.list_References = QtGui.QListWidget() + # layout + mainLayout = QtGui.QVBoxLayout() + mainLayout.addWidget(self._helpTextLbl) + mainLayout.addWidget(self.pushButton_Add) + mainLayout.addWidget(self.list_References) + self.setLayout(mainLayout) + # signals and slots + self.list_References.itemSelectionChanged.connect(self.select_clicked_reference_shape) + self.list_References.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) + self.list_References.connect(self.list_References, QtCore.SIGNAL("customContextMenuRequested(QPoint)"), self.references_list_right_clicked) + QtCore.QObject.connect(self.pushButton_Add, QtCore.SIGNAL("clicked()"), self.add_references) + + def get_references(self): + for ref in self.tuplereferences: + for elem in ref[1]: + self.references.append((ref[0], elem)) + + def get_item_text(self, ref): + return (ref[0].Name + ':' + ref[1]) + + def get_allitems_text(self): + items = [] + for ref in self.references: + items.append(self.get_item_text(ref)) + return sorted(items) + + def rebuild_list_References(self, current_row=0): + self.list_References.clear() + for listItemName in self.get_allitems_text(): + self.list_References.addItem(listItemName) + if current_row > self.list_References.count() - 1: # first row is 0 + current_row = self.list_References.count() - 1 + if self.list_References.count() > 0: + self.list_References.setCurrentItem(self.list_References.item(current_row)) + + def select_clicked_reference_shape(self): + self.setback_listobj_visibility() + if self.sel_server: + FreeCADGui.Selection.removeObserver(self.sel_server) + self.sel_server = None + if not self.sel_server: + if not self.references: + return + currentItemName = str(self.list_References.currentItem().text()) + for ref in self.references: + if self.get_item_text(ref) == currentItemName: + # print('found: shape: ' + ref[0].Name + ' element: ' + ref[1]) + if not ref[0].ViewObject.Visibility: + self.obj_notvisible.append(ref[0]) + ref[0].ViewObject.Visibility = True + FreeCADGui.Selection.clearSelection() + FreeCADGui.Selection.addSelection(ref[0], ref[1]) + + def setback_listobj_visibility(self): + '''set back Visibility of the list objects + ''' + FreeCADGui.Selection.clearSelection() + for obj in self.obj_notvisible: + obj.ViewObject.Visibility = False + self.obj_notvisible = [] + + def references_list_right_clicked(self, QPos): + self.contextMenu = QtGui.QMenu() + menu_item_remove_selected = self.contextMenu.addAction("Remove selected geometry") + menu_item_remove_all = self.contextMenu.addAction("Clear list") + if not self.references: + menu_item_remove_selected.setDisabled(True) + menu_item_remove_all.setDisabled(True) + self.connect(menu_item_remove_selected, QtCore.SIGNAL("triggered()"), self.remove_selected_reference) + self.connect(menu_item_remove_all, QtCore.SIGNAL("triggered()"), self.remove_all_references) + parentPosition = self.list_References.mapToGlobal(QtCore.QPoint(0, 0)) + self.contextMenu.move(parentPosition + QPos) + self.contextMenu.show() + + def remove_selected_reference(self): + if not self.references: + return + currentItemName = str(self.list_References.currentItem().text()) + currentRow = self.list_References.currentRow() + for ref in self.references: + if self.get_item_text(ref) == currentItemName: + self.references.remove(ref) + self.rebuild_list_References(currentRow) + + def remove_all_references(self): + self.references = [] + 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 + self.setback_listobj_visibility() + FreeCADGui.Selection.clearSelection() + # start SelectionObserver and parse the function to add the References to the widget + print_message = "Select Faces by single click on them to add them to the list" + if not self.sel_server: + # if we do not check, we would start a new SelectionObserver on every click on addReference button + # but close only one SelectionObserver on leaving the task panel + from . 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"): + if selection[1]: + elt = selection[0].Shape.getElement(selection[1]) + if elt.ShapeType == 'Face': + if selection not in self.references: + self.references.append(selection) + self.rebuild_list_References(self.get_allitems_text().index(self.get_item_text(selection))) + else: + FreeCAD.Console.PrintMessage(selection[0].Name + ' --> ' + selection[1] + ' is in reference list already!\n') diff --git a/src/Mod/Fem/femguiobjects/_ViewProviderFemElementGeometry2D.py b/src/Mod/Fem/femguiobjects/_ViewProviderFemElementGeometry2D.py index 8d1bbe962d..356920e9ee 100644 --- a/src/Mod/Fem/femguiobjects/_ViewProviderFemElementGeometry2D.py +++ b/src/Mod/Fem/femguiobjects/_ViewProviderFemElementGeometry2D.py @@ -34,7 +34,7 @@ False if False else FemGui.__name__ # dummy usage of FemGui for flake8, just re # for the panel from PySide import QtCore -from PySide import QtGui +from . import FemSelectionWidgets class _ViewProviderFemElementGeometry2D: @@ -103,151 +103,37 @@ class _TaskPanelFemElementGeometry2D: '''The TaskPanel for editing References property of FemElementGeometry2D objects''' def __init__(self, obj): - FreeCADGui.Selection.clearSelection() - self.sel_server = None + + # parameter widget self.obj = obj - self.obj_notvisible = [] - - self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/Resources/ui/ElementGeometry2D.ui") - QtCore.QObject.connect(self.form.if_thickness, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.thickness_changed) - QtCore.QObject.connect(self.form.pushButton_Reference, QtCore.SIGNAL("clicked()"), self.add_references) - self.form.list_References.itemSelectionChanged.connect(self.select_clicked_reference_shape) - 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_shellthickness_props() - self.update() + self.parameterWidget = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/Resources/ui/ElementGeometry2D.ui") + self.init_parameter_widget() + QtCore.QObject.connect(self.parameterWidget.if_thickness, QtCore.SIGNAL("valueChanged(Base::Quantity)"), self.thickness_changed) + # geometry selection widget + self.selectionWidget = FemSelectionWidgets.FacesSelection(obj.References) + # form made from param and selection widget + self.form = [self.parameterWidget, self.selectionWidget] def accept(self): - self.setback_listobj_visibility() - self.set_shellthickness_props() - if self.sel_server: - FreeCADGui.Selection.removeObserver(self.sel_server) - FreeCADGui.ActiveDocument.resetEdit() + self.obj.Thickness = self.thickness + self.obj.References = self.selectionWidget.references FreeCAD.ActiveDocument.recompute() + self.set_back_all() return True def reject(self): - self.setback_listobj_visibility() - if self.sel_server: - FreeCADGui.Selection.removeObserver(self.sel_server) - FreeCADGui.ActiveDocument.resetEdit() + self.set_back_all() return True - def get_shellthickness_props(self): + def init_parameter_widget(self): self.thickness = self.obj.Thickness - self.references = [] - if self.obj.References: - self.tuplereferences = self.obj.References - self.get_references() - - def set_shellthickness_props(self): - self.obj.References = self.references - self.obj.Thickness = self.thickness - - def update(self): - 'fills the widgets' - self.form.if_thickness.setText(self.thickness.UserString) - self.rebuild_list_References() + self.parameterWidget.if_thickness.setText(self.thickness.UserString) def thickness_changed(self, base_quantity_value): self.thickness = base_quantity_value - 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_remove_selected = self.form.contextMenu.addAction("Remove selected reference") - menu_item_remove_all = self.form.contextMenu.addAction("Remove all references") - if not self.references: - menu_item_remove_selected.setDisabled(True) - menu_item_remove_all.setDisabled(True) - self.form.connect(menu_item_remove_selected, QtCore.SIGNAL("triggered()"), self.remove_selected_reference) - self.form.connect(menu_item_remove_all, QtCore.SIGNAL("triggered()"), self.remove_all_references) - parentPosition = self.form.list_References.mapToGlobal(QtCore.QPoint(0, 0)) - self.form.contextMenu.move(parentPosition + QPos) - self.form.contextMenu.show() - - def remove_selected_reference(self): - if not self.references: - return - currentItemName = str(self.form.list_References.currentItem().text()) - currentRow = self.form.list_References.currentRow() - 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(currentRow) - - def remove_all_references(self): - self.references = [] - 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 - self.setback_listobj_visibility() - FreeCADGui.Selection.clearSelection() - # start SelectionObserver and parse the function to add the References to the widget - print_message = "Select Faces by single click on them to add them to the list" - if not self.sel_server: - # if we do not check, we would start a new SelectionObserver on every click on addReference button - # but close only one SelectionObserver on leaving the task panel - from . 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"): - if selection[1]: - elt = selection[0].Shape.getElement(selection[1]) - if elt.ShapeType == 'Face': - 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, current_row=0): - 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) - if current_row > self.form.list_References.count() - 1: # first row is 0 - current_row = self.form.list_References.count() - 1 - if self.form.list_References.count() > 0: - self.form.list_References.setCurrentItem(self.form.list_References.item(current_row)) - - def select_clicked_reference_shape(self): - self.setback_listobj_visibility() - if self.sel_server: - FreeCADGui.Selection.removeObserver(self.sel_server) - self.sel_server = None - if not self.sel_server: - 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: - # print('found: shape: ' + ref[0].Name + ' element: ' + ref[1]) - if not ref[0].ViewObject.Visibility: - self.obj_notvisible.append(ref[0]) - ref[0].ViewObject.Visibility = True - FreeCADGui.Selection.clearSelection() - FreeCADGui.Selection.addSelection(ref[0], ref[1]) - - def setback_listobj_visibility(self): - '''set back Visibility of the list objects - ''' - FreeCADGui.Selection.clearSelection() - for obj in self.obj_notvisible: - obj.ViewObject.Visibility = False - self.obj_notvisible = [] + def set_back_all(self): + self.selectionWidget.setback_listobj_visibility() + if self.selectionWidget.sel_server: + FreeCADGui.Selection.removeObserver(self.selectionWidget.sel_server) + FreeCADGui.ActiveDocument.resetEdit()