Force toolbar to invoke IsChecked for commands

Here's the place for discussion related to coding in FreeCAD, C++ or Python. Design, interfaces and structures.
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
project4
Posts: 237
Joined: Fri Jul 12, 2013 12:53 pm

Force toolbar to invoke IsChecked for commands

Post by project4 »

Hi,

Is there a way to force the toolbar to invoke the IsChecked for commands to update the button state?

Scenario:
I have a button that enables/disabled a feature, but that feature can be disabled due to other events, not only the button push.
I have to update the button manually somehow or ask the GUI to update it.
Looks like FreeCADGui.updateGui() doesn't do it...

Thanks.
User avatar
DeepSOIC
Veteran
Posts: 7896
Joined: Fri Aug 29, 2014 12:45 am
Location: used to be Saint-Petersburg, Russia

Re: Force toolbar to invoke IsChecked for commands

Post by DeepSOIC »

I have had a look through the source, and I couldn't find how to update the checked status of a toolbar button through a command class. It is probably unsupported. You can try get hold of the Qt action associated with the command and manipulate the action. I'm afraid I don't know how to do that.
User avatar
DeepSOIC
Veteran
Posts: 7896
Joined: Fri Aug 29, 2014 12:45 am
Location: used to be Saint-Petersburg, Russia

Re: Force toolbar to invoke IsChecked for commands

Post by DeepSOIC »

triplus wrote:ping
@triplus, I've seen the Qt magic you've done with tabbar. Maybe you can help.
triplus
Veteran
Posts: 9471
Joined: Mon Dec 12, 2011 4:45 pm

Re: Force toolbar to invoke IsChecked for commands

Post by triplus »

When you create a standard FreeCAD command a corresponding QAction gets created. And therefore you can get control over such QAction by doing something like:

Code: Select all

from PySide import QtGui
mw = FreeCADGui.getMainWindow()
a = mw.findChild(QtGui.QAction, "CommandName") 
But reading the description i feel that such low level and direct access might not be needed. And there likely is a way for @project4 to achieve what he is after without manipulating the QAction directly. And to stay within the "standard behavior". As when you are manipulating the QAction directly. There is always a chance FreeCAD will already try to manage the QAction in some way and you would end up "fighting" for control. In addition you must usually implement a lot of the logic manually.
project4
Posts: 237
Joined: Fri Jul 12, 2013 12:53 pm

Re: Force toolbar to invoke IsChecked for commands

Post by project4 »

triplus wrote: Sat Jul 21, 2018 11:30 am When you create a standard FreeCAD command a corresponding QAction gets created. And therefore you can get control over such QAction by doing something like:

Code: Select all

from PySide import QtGui
mw = FreeCADGui.getMainWindow()
a = mw.findChild(QtGui.QAction, "CommandName") 
But reading the description i feel that such low level and direct access might not be needed. And there likely is a way for @project4 to achieve what he is after without manipulating the QAction directly. And to stay within the "standard behavior". As when you are manipulating the QAction directly. There is always a chance FreeCAD will already try to manage the QAction in some way and you would end up "fighting" for control. In addition you must usually implement a lot of the logic manually.
Hmmm... Didn't want to get to such low level... expected to have something basic.
As I can see, the toggle button behaviour is not documented at all, so I guess it wasn't well thought or tested.
triplus
Veteran
Posts: 9471
Joined: Mon Dec 12, 2011 4:45 pm

Re: Force toolbar to invoke IsChecked for commands

Post by triplus »

project4
Posts: 237
Joined: Fri Jul 12, 2013 12:53 pm

Re: Force toolbar to invoke IsChecked for commands

Post by project4 »

triplus wrote: Sat Jul 21, 2018 3:00 pm This is likely what you are after:

https://forum.freecadweb.org/viewtopic.php?f=10&t=12208
I read it before. I did found how to implement the logic, but I couldn't find how to trigger the toolbar to update its visual state since it might have changed not by clicking on the button, so the visual state will not be checked or changed.
triplus
Veteran
Posts: 9471
Joined: Mon Dec 12, 2011 4:45 pm

Re: Force toolbar to invoke IsChecked for commands

Post by triplus »

Why would toolbar update the state? Toolbar is just the placeholder.

P.S. Share the code and provide further detail description on what you are trying to do. And others can take a look and try to provide a clue. As you saying the toolbar should control the button state. That doesn't make much sense to me.
project4
Posts: 237
Joined: Fri Jul 12, 2013 12:53 pm

Re: Force toolbar to invoke IsChecked for commands

Post by project4 »

@triplus

As I wrote:

Scenario:
I have a button that enables/disabled a feature, but that feature can be disabled due to other events, not only the button push.

Example:
A toggle button that alters the transparency of the objects on screen.
Press it, the transparency is enabled, the button state is checked - all good.
Lets say the transparency can be disabled by pressing ESC as well, not only by clicking the button again.
You press the ESC, the transparency gets disabled, but the button still stays in the checked state.

There is "Checkable" property that can be returned in GetResources, that I point to a function that checks whether the transparency is currently enabled or not:

Code: Select all

'Checkable':    self.IsChecked()
But that function is not called, so the button stays in "checked" state, even when "IsChecked()" would return False since the feature is OFF.

Hope that explains the situation better...
User avatar
riprider
Posts: 20
Joined: Wed Feb 21, 2024 2:16 pm

Re: Force toolbar to invoke IsChecked for commands

Post by riprider »

Hi - My first post here on the forum and huge FreeCAD fanboy...I ran into this use case recently and thought I should share what I learned in the hope it helps someone down the road. Yes, the issue has been silent for 5 years, but I found so little on the topic and nothing that fully satisfied that I wanted to get it documented here on the Forum.

Goal - Build a macro script to toggle the enabled / disabled status of a toolbar button. I'm talking about the way a button highlights or dims based on its status of on/off (or enabled/disabled).

Why - In my case, I wrote a script to automate some changes to the Draft Snap modes. The code would change the snap modes as desired but it did not change the button status accordingly. This left the UI in an untenable state. Naturally, I set out to write more code to make the changes to the buttons and their visual state.

Code: Select all

#########################################################################
'''                                                                     
This code shows how to togggle the visual state of a toolbar button.
In this case we have chosen to toggle the "Snap Dimensions"
button. The code also provides type names and the button text
fields for other buttons in the snap toolbar so you can modify
as needed to fit your situation. Repeatedly running this script
should "enable/disable" the Snap Dimensions button, but it does not
change the snap modes at all. It only changes the state of the button.
'''
#########################################################################
import FreeCAD as App
import FreeCADGui as Gui 
import PySide2
from PySide import QtGui, QtCore
from PySide.QtGui import QToolBar
ec=0  #exit code
mw = Gui.getMainWindow()                           #get a pointer to the main window so we can then get its children
# the next line creates a list of the main window's children,filtered by type 
tbList = mw.findChildren(QToolBar, "Draft snap"  )  #returns a list of one element
tb=tbList[0]                                        #point to that element
for c in tb.children():                             #iterate thru its children
  myType=str(type(c))                               #we'll filter on the type
  print("Type: ",myType)      #interesting output of the toolbar children types
  if "QToolButton" in myType: #filtering to get only QToolButton types
    print(c.text())           #more valuable output so you can figure out your own filter(s)
    if c.text()=="Snap Dimensions":   #chosen at random for this example
      c.setCheckable(True)   #these are the two lines that change 
      c.toggle()             #the visual highlight on the button in question.
      # The lines above only change the button highlighting, 
      # they do not change the snap modes. These are Qt functions so they
      # are not covered in FreeCAD documentation. See https://doc.qt.io/qtforpython-6/index.html.
# The following line shows what the Snapper considers active. It may differ now
# from what the snapper toolbar buttons  indicate. Restarting FreeCAD will reset the 
# buttons and modes to a clean state.
print("Snapper active snap modes: ", Gui.Snapper.active_snaps) 
print("Exit code: ", ec)

Code: Select all

OS: macOS 13.6
Word size of FreeCAD: 64-bit
Version: 0.21.2.33771 (Git)
Build type: Release
Branch: (HEAD detached at 0.21.2)
Hash: b9bfa5c5507506e4515816414cd27f4851d00489
Python 3.10.13, Qt 5.15.8, Coin 4.0.0, Vtk 9.2.6, OCC 7.6.3
Locale: C/Default (C)
Installed mods: 
  * Render 2022.2.0
  * boltsfc 2022.11.5
  * fasteners 0.4.23
  * ExplodedAssembly
Post Reply