A toggle button in the toolbar

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!
User avatar
shaise
Posts: 470
Joined: Thu Jun 11, 2015 8:11 am

A toggle button in the toolbar

Post by shaise »

Hello FreeCAD developers,

During my work on the Fastener Workbench, I came into a need for a toggle button (or a check box). This button holds a state upon which some calculation is done when generating new fasteners.
However I did not find any support for such a button, nor did I find any example that do that.
To overcome this problem I used a small hack - every time the button is activated, I search the entire raw gui for this button, and then use setIcon() to switch the icon to another one giving me an effective toggle button:
toggle.png
toggle.png (7.86 KiB) Viewed 3803 times
Here is the gui search code:

Code: Select all

def FSGetToolbarItem(toolbar_name, command_name):
  mw = QtGui.qApp.activeWindow()
  tb = None
  for c in mw.children():
    if isinstance(c, QtGui.QToolBar) and c.windowTitle() == toolbar_name:
      tb = c
      break
  if tb == None:
    return None
  for c in tb.children():
    if isinstance(c, QtGui.QToolButton) and c.text() == command_name:
      return c
  return None
This seemed to work nice, until i stepped into a small issue: whenever I open a task dialog, then close it, this button reverts to the original icon regardless of the state. I fixed this problem by using a small timer that re-fixes the icon a split second after the dialog is closed, but this is very very ugly hack.
Is there any standard way to add a toggle button to the workbench toolbar? or at least a way to access the command object itself and change the icon there?

Thanks!
shai
Fat-Zer
Posts: 176
Joined: Thu Oct 30, 2014 10:38 pm

Re: A toggle button in the toolbar

Post by Fat-Zer »

I don't know about python but in C++ you can change the icon in overloaded updateAction() of the command associated with the button like in the Sketcher's CreateGeo commands...
User avatar
shaise
Posts: 470
Joined: Thu Jun 11, 2015 8:11 am

Re: A toggle button in the toolbar

Post by shaise »

Fat-Zer wrote:I don't know about python but in C++ you can change the icon in overloaded updateAction() of the command associated with the button like in the Sketcher's CreateGeo commands...
Thanks! I will take a look and see if there is something similar in python.
wmayer
Founder
Posts: 20243
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: A toggle button in the toolbar

Post by wmayer »

Currently, there is no direct way in the Python interface to support toggle buttons.
User avatar
shaise
Posts: 470
Joined: Thu Jun 11, 2015 8:11 am

Re: A toggle button in the toolbar

Post by shaise »

wmayer wrote:Currently, there is no direct way in the Python interface to support toggle buttons.
Thank you,

I will leave it as it is now then.
User avatar
PrzemoF
Veteran
Posts: 3520
Joined: Fri Jul 25, 2014 4:52 pm
Contact:

Re: A toggle button in the toolbar

Post by PrzemoF »

I need toggle button as well.. I have frequency analysis in FEM wb in fairly anvanced stage and switching between static analysis and frequency analysis should be easily accesible for user (I don't want to have it in the Preferences, except the default value maybe). We have 2 separate analysis buttons ("normal" and "quick") and having a toggle button controlling a settings for both seems to be a good idea.

Would it be hard to implement the toggle button?
wmayer
Founder
Posts: 20243
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: A toggle button in the toolbar

Post by wmayer »

What exactly do you need? The same as shaise or a toggle button as Qt offers it? FYI, usually a toggle button is on or off but doesn't change its icon. To see what I mean in FreeCAD e.g. we have the orthographic and perspective projection buttons in the View menu.
User avatar
PrzemoF
Veteran
Posts: 3520
Joined: Fri Jul 25, 2014 4:52 pm
Contact:

Re: A toggle button in the toolbar

Post by PrzemoF »

That perspective/ortho view switching will be enough for now for me - thanks!
User avatar
shaise
Posts: 470
Joined: Thu Jun 11, 2015 8:11 am

Re: A toggle button in the toolbar

Post by shaise »

I can also use the perspective/ortho type of button, but, as the perspective/ortho I will need two buttons and a way to release one button when the other is pressed.
The best way for me, is like the "Activated(self)" callback in the command class, there will be something like a "Pressed(self)" callback letting me set the state of the toggle button.
But i will gladly use any other way you may suggest
wmayer
Founder
Posts: 20243
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: A toggle button in the toolbar

Post by wmayer »

shaise wrote:I can also use the perspective/ortho type of button, but, as the perspective/ortho I will need two buttons and a way to release one button when the other is pressed.
The best way for me, is like the "Activated(self)" callback in the command class, there will be something like a "Pressed(self)" callback letting me set the state of the toggle button.
But i will gladly use any other way you may suggest
If I got you right then you can use a Python command group. The example taken from Commands.py is:

Code: Select all

class TemplatePyGrp_1:
    def Activated(self):
        import FreeCAD
        FreeCAD.Console.PrintMessage("TemplatePyGrp_1\n")

    def GetResources(self):
        return {'Pixmap'  : 'Part_JoinConnect', 'MenuText': 'TemplatePyGrp_1', 'ToolTip': 'Print a message'}

class TemplatePyGrp_2:
    def Activated(self):
        import FreeCAD
        FreeCAD.Console.PrintMessage("TemplatePyGrp_2\n")

    def GetResources(self):
        return {'Pixmap'  : 'Part_JoinEmbed', 'MenuText': 'TemplatePyGrp_2', 'ToolTip': 'Print a message'}

class TemplatePyGrp_3:
    def Activated(self):
        import FreeCAD
        FreeCAD.Console.PrintMessage("TemplatePyGrp_3\n")

    def GetResources(self):
        return {'Pixmap'  : 'Part_JoinCutout', 'MenuText': 'TemplatePyGrp_3', 'ToolTip': 'Print a message'}

class TemplatePyGroup:
    "Example group command class"
    #def Activated(self, index):
    #    print "TemplatePyGroup activated ;-) "

    def GetCommands(self):
        return ("TemplatePyGrp_1", "TemplatePyGrp_2", "TemplatePyGrp_3", "Std_New")

    def GetDefaultCommand(self):
        return 2

    def GetResources(self):
        return {'Pixmap'  : 'python', 'MenuText': 'Group command', 'ToolTip': 'Example group command'}

FreeCADGui.addCommand('TemplatePyGrp_1',TemplatePyGrp_1())
FreeCADGui.addCommand('TemplatePyGrp_2',TemplatePyGrp_2())
FreeCADGui.addCommand('TemplatePyGrp_3',TemplatePyGrp_3())
FreeCADGui.addCommand('TemplatePyGroup',TemplatePyGroup())
With git commit 27dc80c84 toggle commands are supported now. In Qt terminology this is called 'checkable', not 'toggle'.
Example:

Code: Select all

class TemplatePyCheckable:
    "Example toggle command class"
    def Activated(self, index):
        if index == 0:
            print "Toggle is off"
        else:
            print "Toggle is on"

    def GetResources(self):
        return {'Pixmap'  : 'python', 'MenuText': 'Toggle command', 'ToolTip': 'Example toggle command', 'Checkable': True}

FreeCADGui.addCommand('TemplatePyCheckable',TemplatePyCheckable())


Note:
1. The changes compared to a normal command is that the 'Activated' has a second parameter of type int which is 0 for off and 1 for on.
2. The dict returned by GetResources must have the key 'Checkable'. If this key is present the command becomes a toggle command. If the value is True the command is set to on by default, if it's False it is set to off. If the value cannot be interpreted as a boolean an exception is raised.
Post Reply