diff --git a/src/Mod/BIM/Arch.py b/src/Mod/BIM/Arch.py index 3e89a9b11b..459399a560 100644 --- a/src/Mod/BIM/Arch.py +++ b/src/Mod/BIM/Arch.py @@ -2231,7 +2231,6 @@ def debaseWall(wall): return False doc = wall.Document - doc.openTransaction(f"Debase Wall: {wall.Label}") try: # --- Calculation of the final placement --- @@ -2296,11 +2295,8 @@ def debaseWall(wall): doc.recompute() except Exception as e: - doc.abortTransaction() FreeCAD.Console.PrintError(f"Error debasing wall '{wall.Label}': {e}\n") return False - finally: - doc.commitTransaction() return True diff --git a/src/Mod/BIM/ArchComponent.py b/src/Mod/BIM/ArchComponent.py index 961c91bae0..dabcbbcba5 100644 --- a/src/Mod/BIM/ArchComponent.py +++ b/src/Mod/BIM/ArchComponent.py @@ -2092,6 +2092,10 @@ class ComponentTaskPanel: """ def __init__(self): + """ + Initializes the task panel. The transaction context is implicitly opened by the C++ layer + when entering edit mode. + """ # the panel has a tree widget that contains categories # for the subcomponents, such as additions, subtractions. # the categories are shown only if they are not empty. @@ -2176,6 +2180,8 @@ class ComponentTaskPanel: ) self.update() + self.doc = FreeCAD.ActiveDocument + def isAllowedAlterSelection(self): """Indicate whether this task dialog allows other commands to modify the selection while it is open. @@ -2201,9 +2207,9 @@ class ComponentTaskPanel: return True def getStandardButtons(self): - """Add the standard ok button.""" + """Add the standard Ok/Cancel buttons.""" - return QtGui.QDialogButtonBox.Ok + return QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel def check(self, wid, col): """This method is run as the callback when the user selects an item in the tree. @@ -2319,6 +2325,7 @@ class ComponentTaskPanel: mod = a for o in FreeCADGui.Selection.getSelection(): addToComponent(self.obj, o, mod) + self.obj.recompute() self.update() def removeElement(self): @@ -2340,18 +2347,29 @@ class ComponentTaskPanel: # Fallback for older proxies that might not have the method removeFromComponent(self.obj, element_to_remove) + self.obj.recompute() self.update() def accept(self): """This method runs as a callback when the user selects the ok button. Recomputes the document, and leave edit mode. - """ + The transaction is implicitly committed by the C++ layer during resetEdit. + """ FreeCAD.ActiveDocument.recompute() FreeCADGui.ActiveDocument.resetEdit() return True + def reject(self): + """ + Aborts the edit session. An explicit abort is required to prevent the C++ layer from + committing changes during resetEdit. + """ + self.doc.abortTransaction() + FreeCADGui.ActiveDocument.resetEdit() + return True + def editObject(self, wid, col): """This method is run when the user double clicks on an item in the tree widget. diff --git a/src/Mod/BIM/ArchWall.py b/src/Mod/BIM/ArchWall.py index e51175da03..466d17a061 100644 --- a/src/Mod/BIM/ArchWall.py +++ b/src/Mod/BIM/ArchWall.py @@ -1780,6 +1780,75 @@ class _Wall(ArchComponent.Component): return base_faces, placement +if FreeCAD.GuiUp: + + class WallTaskPanel(ArchComponent.ComponentTaskPanel): + def __init__(self, obj): + ArchComponent.ComponentTaskPanel.__init__(self) + self.obj = obj + self.wallWidget = QtGui.QWidget() + self.wallWidget.setWindowTitle(translate("Arch", "Wall Options")) + + layout = QtGui.QFormLayout(self.wallWidget) + + self.length = FreeCADGui.UiLoader().createWidget("Gui::InputField") + self.length.setProperty("unit", "mm") + self.length.setText(obj.Length.UserString) + layout.addRow(translate("Arch", "Length"), self.length) + + self.width = FreeCADGui.UiLoader().createWidget("Gui::InputField") + self.width.setProperty("unit", "mm") + self.width.setText(obj.Width.UserString) + layout.addRow(translate("Arch", "Width"), self.width) + + self.height = FreeCADGui.UiLoader().createWidget("Gui::InputField") + self.height.setProperty("unit", "mm") + self.height.setText(obj.Height.UserString) + layout.addRow(translate("Arch", "Height"), self.height) + + self.alignLayout = QtGui.QHBoxLayout() + self.alignLeft = QtGui.QRadioButton(translate("Arch", "Left")) + self.alignCenter = QtGui.QRadioButton(translate("Arch", "Center")) + self.alignRight = QtGui.QRadioButton(translate("Arch", "Right")) + self.alignLayout.addWidget(self.alignLeft) + self.alignLayout.addWidget(self.alignCenter) + self.alignLayout.addWidget(self.alignRight) + self.alignLayout.addStretch() + + self.alignGroup = QtGui.QButtonGroup(self.wallWidget) + self.alignGroup.addButton(self.alignLeft) + self.alignGroup.addButton(self.alignCenter) + self.alignGroup.addButton(self.alignRight) + self.alignGroup.buttonClicked.connect(self.setAlign) + + if obj.Align == "Left": + self.alignLeft.setChecked(True) + elif obj.Align == "Right": + self.alignRight.setChecked(True) + else: + self.alignCenter.setChecked(True) + + layout.addRow(translate("Arch", "Alignment"), self.alignLayout) + + # Wall Options first, then Components (inherited self.form) + self.form = [self.wallWidget, self.form] + + def setAlign(self, button): + if button == self.alignLeft: + self.obj.Align = "Left" + elif button == self.alignRight: + self.obj.Align = "Right" + else: + self.obj.Align = "Center" + self.obj.recompute() + + def accept(self): + self.obj.Length = self.length.text() + self.obj.Width = self.width.text() + self.obj.Height = self.height.text() + return super().accept() + + class _ViewProviderWall(ArchComponent.ViewProviderComponent): """The view provider for the wall object. @@ -1965,6 +2034,14 @@ class _ViewProviderWall(ArchComponent.ViewProviderComponent): return "Wireframe" return ArchComponent.ViewProviderComponent.setDisplayMode(self, mode) + def setEdit(self, vobj, mode): + if mode != 0: + return None + taskd = WallTaskPanel(vobj.Object) + taskd.update() + FreeCADGui.Control.showDialog(taskd) + return True + def setupContextMenu(self, vobj, menu): if FreeCADGui.activeWorkbench().name() != "BIMWorkbench":