From 3f49793794e3210e0e5a92f789b8fa00ddc0fefd Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 26 Jan 2026 10:42:20 -0600 Subject: [PATCH] cam: attempt to fix issue #26652 ie. fix issue with state of recompute button for tool bit (#26884) * cam: attempt to fix issue #26652 ie. fix issue with state of recompute button for tool bit * add unit test for issue #26652 * run precommit * relocate `purgeTouched()` call to end of `_update_visual_representation` function --- .../CAM/CAMTests/TestToolBitRecomputeState.py | 51 +++++++++++++++++++ src/Mod/CAM/CMakeLists.txt | 1 + src/Mod/CAM/Path/Tool/toolbit/models/base.py | 3 ++ src/Mod/CAM/TestCAMApp.py | 1 + 4 files changed, 56 insertions(+) create mode 100644 src/Mod/CAM/CAMTests/TestToolBitRecomputeState.py diff --git a/src/Mod/CAM/CAMTests/TestToolBitRecomputeState.py b/src/Mod/CAM/CAMTests/TestToolBitRecomputeState.py new file mode 100644 index 0000000000..50eab843b2 --- /dev/null +++ b/src/Mod/CAM/CAMTests/TestToolBitRecomputeState.py @@ -0,0 +1,51 @@ +# *************************************************************************** +# * Copyright (c) 2026 Chris Jones github.com/ipatch * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * 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. * +# *************************************************************************** + +import FreeCAD +from CAMTests.PathTestUtils import PathTestWithAssets +from Path.Tool.toolbit import ToolBitEndmill + + +class TestToolBitRecomputeState(PathTestWithAssets): + """Test toolbit recompute state handling (issue #26652)""" + + def setUp(self): + """Set up test fixtures""" + super().setUp() + self.doc = FreeCAD.newDocument("TestToolbitState") + + def tearDown(self): + """Clean up after tests""" + FreeCAD.closeDocument(self.doc.Name) + super().tearDown() + + def testToolbitExpressionRecomputeState(self): + """Test that toolbit with unitless expression doesn't stay touched after recompute""" + # create an endmill shape and toolbit + shape = self.assets.get("toolbitshape://endmill") + toolbit = ToolBitEndmill(shape, id="test_endmill") + + # attach to document + obj = toolbit.attach_to_doc(self.doc, label="TestEndmill") + + # set initial diameter + obj.Diameter = FreeCAD.Units.Quantity("5 mm") + self.doc.recompute() + + # now set expression without unit - this triggers issue #26652 + obj.setExpression("Diameter", "5") + self.doc.recompute() + + # after recompute, toolbit should not be in touched state + self.assertFalse( + "Touched" in obj.State, + "Toolbit with unitless expression should not be touched after recompute", + ) diff --git a/src/Mod/CAM/CMakeLists.txt b/src/Mod/CAM/CMakeLists.txt index f1e5af3042..656a16c555 100644 --- a/src/Mod/CAM/CMakeLists.txt +++ b/src/Mod/CAM/CMakeLists.txt @@ -585,6 +585,7 @@ SET(Tests_SRCS CAMTests/Tools/Bit/test-path-tool-bit-bit-00.fctb CAMTests/Tools/Library/test-path-tool-bit-library-00.fctl CAMTests/Tools/Shape/test-path-tool-bit-shape-00.fcstd + CAMTests/TestToolBitRecomputeState.py ) SET(Tests_Fixtures diff --git a/src/Mod/CAM/Path/Tool/toolbit/models/base.py b/src/Mod/CAM/Path/Tool/toolbit/models/base.py index 42a940aa1c..a47658839b 100644 --- a/src/Mod/CAM/Path/Tool/toolbit/models/base.py +++ b/src/Mod/CAM/Path/Tool/toolbit/models/base.py @@ -914,6 +914,9 @@ class ToolBit(Asset, ABC): ) raise + # clear the touched state since visual updates shouldn't require recompute + self.obj.purgeTouched() + def to_dict(self): """ Returns a dictionary representation of the tool bit. diff --git a/src/Mod/CAM/TestCAMApp.py b/src/Mod/CAM/TestCAMApp.py index e56a6f3891..b001a13e55 100644 --- a/src/Mod/CAM/TestCAMApp.py +++ b/src/Mod/CAM/TestCAMApp.py @@ -80,6 +80,7 @@ from CAMTests.TestPathToolAssetManager import TestPathToolAssetManager from CAMTests.TestPathToolAssetStore import TestPathToolFileStore, TestPathToolMemoryStore from CAMTests.TestPathToolAssetUri import TestPathToolAssetUri from CAMTests.TestPathToolBit import TestPathToolBit +from CAMTests.TestToolBitRecomputeState import TestToolBitRecomputeState from CAMTests.TestPathToolShapeClasses import TestPathToolShapeClasses from CAMTests.TestPathToolShapeDoc import TestPathToolShapeDoc from CAMTests.TestPathToolShapeIcon import (