diff --git a/src/Mod/BIM/InitGui.py b/src/Mod/BIM/InitGui.py index 98e23d4487..cab80aaca2 100644 --- a/src/Mod/BIM/InitGui.py +++ b/src/Mod/BIM/InitGui.py @@ -30,10 +30,10 @@ import Arch_rc class BIMWorkbench(Workbench): def __init__(self): - + def QT_TRANSLATE_NOOP(context, text): return text - + bdir = os.path.join(FreeCAD.getResourceDir(), "Mod", "BIM") tt = QT_TRANSLATE_NOOP("BIM","The BIM workbench is used to model buildings") self.__class__.MenuText = QT_TRANSLATE_NOOP("BIM", "BIM") @@ -46,10 +46,10 @@ class BIMWorkbench(Workbench): # add translations and icon paths FreeCADGui.addIconPath(":/icons") FreeCADGui.addLanguagePath(":/translations") - + # Create menus and toolbars self.createTools() - + # Load Arch & Draft preference pages self.loadPreferences() @@ -58,7 +58,7 @@ class BIMWorkbench(Workbench): def createTools(self): - + "Create tolbars and menus" def QT_TRANSLATE_NOOP(context, text): @@ -130,7 +130,7 @@ class BIMWorkbench(Workbench): "Arch_Equipment", "Arch_Rebar", ] - + self.generictools = [ "Arch_Profile", "BIM_Box", @@ -237,9 +237,9 @@ class BIMWorkbench(Workbench): "BIM_Nudge_Extend", "BIM_Nudge_Shrink", ] - + # append BIM snaps - + from draftutils import init_tools self.snapbar = init_tools.get_draft_snap_commands() self.snapmenu = self.snapbar + [ @@ -247,9 +247,9 @@ class BIMWorkbench(Workbench): "BIM_SetWPFront", "BIM_SetWPSide", ] - + # create generic tools command - + class BIM_GenericTools: def __init__(self, tools): self.tools = tools @@ -392,7 +392,7 @@ class BIMWorkbench(Workbench): for c in FastenerBase.FSGetCommands("screws") if not isinstance(c, tuple) ] - + # load nativeifc tools ifctools = ifc_commands.get_commands() @@ -493,15 +493,17 @@ class BIMWorkbench(Workbench): from DraftGui import todo import BimStatusBar from nativeifc import ifc_observer - + from draftutils import grid_observer + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") if hasattr(FreeCADGui, "draftToolBar"): FreeCADGui.draftToolBar.Activated() if hasattr(FreeCADGui, "Snapper"): FreeCADGui.Snapper.show() - if hasattr(WorkingPlane, "_view_observer_start"): - WorkingPlane._view_observer_start() + WorkingPlane._view_observer_start() + grid_observer._view_observer_setup() + if PARAMS.GetBool("FirstTime", True) and (not hasattr(FreeCAD, "TestEnvironment")): todo.delay(FreeCADGui.runCommand, "BIM_Welcome") todo.delay(BimStatusBar.setStatusIcons, True) @@ -543,10 +545,10 @@ class BIMWorkbench(Workbench): w.toggleViewAction().setVisible(True) self.setupMultipleObjectSelection() - + # add NativeIFC document observer ifc_observer.add_observer() - + # adding a Help menu manipulator # https://github.com/FreeCAD/FreeCAD/pull/10933 class BIM_WBManipulator: @@ -565,13 +567,14 @@ class BIMWorkbench(Workbench): def Deactivated(self): - + from DraftGui import todo import BimStatusBar from bimcommands import BimViews import WorkingPlane from nativeifc import ifc_observer - + from draftutils import grid_observer + PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM") if hasattr(self, "BimSelectObserver"): @@ -582,9 +585,8 @@ class BIMWorkbench(Workbench): FreeCADGui.draftToolBar.Deactivated() if hasattr(FreeCADGui, "Snapper"): FreeCADGui.Snapper.hide() - - if hasattr(WorkingPlane, "_view_observer_stop"): - WorkingPlane._view_observer_stop() + WorkingPlane._view_observer_stop() + grid_observer._view_observer_setup() # print("Deactivating status icon") todo.delay(BimStatusBar.setStatusIcons, False) diff --git a/src/Mod/Draft/CMakeLists.txt b/src/Mod/Draft/CMakeLists.txt index ec4d748304..3a70b64b33 100644 --- a/src/Mod/Draft/CMakeLists.txt +++ b/src/Mod/Draft/CMakeLists.txt @@ -79,6 +79,7 @@ SET(Draft_utilities draftutils/translate.py draftutils/messages.py draftutils/README.md + draftutils/grid_observer.py ) SET(Draft_functions diff --git a/src/Mod/Draft/InitGui.py b/src/Mod/Draft/InitGui.py index 8ed333f87a..72b2b09e0f 100644 --- a/src/Mod/Draft/InitGui.py +++ b/src/Mod/Draft/InitGui.py @@ -155,6 +155,8 @@ class DraftWorkbench(FreeCADGui.Workbench): dsb.show_draft_statusbar() import WorkingPlane WorkingPlane._view_observer_start() # Updates the draftToolBar when switching views. + from draftutils import grid_observer + grid_observer._view_observer_setup() FreeCAD.Console.PrintLog("Draft workbench activated.\n") def Deactivated(self): @@ -167,6 +169,8 @@ class DraftWorkbench(FreeCADGui.Workbench): dsb.hide_draft_statusbar() import WorkingPlane WorkingPlane._view_observer_stop() + from draftutils import grid_observer + grid_observer._view_observer_setup() FreeCAD.Console.PrintLog("Draft workbench deactivated.\n") def ContextMenu(self, recipient): diff --git a/src/Mod/Draft/draftutils/grid_observer.py b/src/Mod/Draft/draftutils/grid_observer.py new file mode 100644 index 0000000000..b873810393 --- /dev/null +++ b/src/Mod/Draft/draftutils/grid_observer.py @@ -0,0 +1,117 @@ +# *************************************************************************** +# * * +# * Copyright (c) 2024 Syres * +# * Copyright (c) 2024 Furgo * +# * * +# * 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 * +# * * +# *************************************************************************** +"""Provide the grid observer for the Draft and BIM workbenches. +""" + +import FreeCAD + + +# View observer code to update the Draft_ToggleGrid command button to reflect +# the grid's visibility status. +# Based on view observer code to update the Draft Tray. +if FreeCAD.GuiUp: + import FreeCADGui + from PySide import QtWidgets + from draftutils import gui_utils + from draftutils.todo import ToDo + + def _update_grid_gui(): + """Update function executed by the callback to refresh the Toggle Grid + button state on all toolbars and menus. + """ + + try: + # Get the active view. + view = gui_utils.get_3d_view() + + # If the active view is not a 3D view, uncheck the button. + if view is None: + _set_grid_button_state(False) + return + + # Otherwise, if there is a view, update the button's checked state. + + # Retrieve the associated grid for each MDI document. + # [1] is the index where the grid is stored in the + # trackers list. See setTrackers(). + view_idx = FreeCADGui.Snapper.trackers[0].index(view) + grid = FreeCADGui.Snapper.trackers[1][view_idx] + if grid.Visible: + _set_grid_button_state(True) + else: + _set_grid_button_state(False) + + except Exception: + pass + + def _view_observer_callback(): + """Callback function to update the Toggle Grid button. + + The update will only happen if either the Draft or BIM + workbenches are active. + """ + + ToDo.delay(_update_grid_gui, None) + + _view_observer_active = False + + def _view_observer_setup(): + """Start or stop the grid observer. + + Start: it is intended to happen when either the Draft or BIM workbench + are activated. The _view_observer_callback is connected to Qt's + subWindowActivated signal. The MDI area emits the subWindowActivated() + signal when the active window changes. + + Stop: This happens when either the Draft or BIM workbenches are + deactivated and is the reverse of the start operation. + """ + + mw = FreeCADGui.getMainWindow() + mdi = mw.findChild(QtWidgets.QMdiArea) + global _view_observer_active + if not _view_observer_active: + # Connect callback to subWindowActivated signal + mdi.subWindowActivated.connect(_view_observer_callback) + _view_observer_active = True + # Trigger initial grid button update + _view_observer_callback() + else: + mdi.subWindowActivated.disconnect(_view_observer_callback) + _view_observer_active = False + + def _set_grid_button_state(button_check): + """Sets the checked state of the Draft_ToggleGrid command. + This is then reflected on the associated "Toggle Grid" buttons of every + toolbar and menu. + + Args: + button_check (bool): if True, check the grid button. + + Returns: + None + """ + + action = FreeCADGui.Command.get("Draft_ToggleGrid").getAction()[0] + action.setCheckable(True) + action.setChecked(button_check)