Source code for gui.toolbar
#
##
## This file is part of pyFormex 1.0.7 (Mon Jun 17 12:20:39 CEST 2019)
## pyFormex is a tool for generating, manipulating and transforming 3D
## geometrical models by sequences of mathematical operations.
## Home page: http://pyformex.org
## Project page: http://savannah.nongnu.org/projects/pyformex/
## Copyright 2004-2019 (C) Benedict Verhegghe (benedict.verhegghe@ugent.be)
## Distributed under the GNU General Public License version 3 or later.
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## 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 General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program. If not, see http://www.gnu.org/licenses/.
##
"""Toolbars for the pyFormex GUI.
This module defines the functions for creating the pyFormex window toolbars.
"""
from __future__ import absolute_import, division, print_function
import pyformex as pf
from pyformex import utils
from pyformex.gui import QtGui, QPixmap
from pyformex.gui import widgets
################### General Button Functions ###########
[docs]def addButton(toolbar, tooltip, icon, func, repeat=False, toggle=False, checked=False, icon0=None, enabled=True):
"""Add a button to a toolbar.
- `toolbar`: the toolbar where the button will be added
- `tooltip`: the text to appear as tooltip
- `icon`: name of the icon to be displayed on the button,
- `func`: function to be called when the button is pressed,
- `repeat`: if True, the `func` will repeatedly be called if button is
held down.
- `toggle`: if True, the button is a toggle and stays in depressed state
until pressed again.
- `checked`: initial state for a toggle buton.
- `icon1`: for a toggle button, icon to display when button is not checked.
"""
iconset = QtGui.QIcon()
icon_on = QPixmap(utils.findIcon(icon))
iconset.addPixmap(icon_on, QtGui.QIcon.Normal, QtGui.QIcon.On)
if toggle and icon0:
icon_off = QPixmap(utils.findIcon(icon0))
iconset.addPixmap(icon_off, QtGui.QIcon.Normal, QtGui.QIcon.Off)
a = toolbar.addAction(iconset, tooltip, func)
a.setEnabled(enabled)
b = toolbar.widgetForAction(a)
if repeat:
b.setAutoRepeat(True)
b.setAutoRepeatDelay(500)
b.clicked.connect(a.trigger)
if toggle:
b.setCheckable(True)
b.clicked.connect(b.toggle)
b.setChecked(checked)
b.setToolTip(tooltip)
return b
[docs]def removeButton(toolbar, button):
"""Remove a button from a toolbar."""
toolbar.removeAction(button)
################### Script action toolbar ###########
[docs]def addActionButtons(toolbar):
"""Add the script action buttons to the toolbar."""
from pyformex.gui import draw
from pyformex.gui.menus import File
action = {}
avail_buttons = [
("Play", "next", draw.play, False),
("ReRun", "rerun", draw.replay, False),
## ( "Step", "nextstop", draw.step, False ),
("Continue", "ff", draw.fforward, False),
("Stop", "stop", draw.raiseExit, False),
("Edit", "pencil", File.editApp, False),
("Info", "info", draw.showDoc, False),
]
# Filter configured buttons
show_buttons = pf.cfg['gui/actionbuttons']
show_buttons = [b for b in avail_buttons if b[0].lower() in show_buttons]
for name, icon, func, enabled in show_buttons:
action[name] = addButton(toolbar, '', icon, func, enabled=enabled)
return action
################# Camera action toolbar ###############
[docs]def addCameraButtons(toolbar):
"""Add the camera buttons to a toolbar."""
# The buttons have the following fields:
# 0 : tooltip
# 1 : icon
# 2 : function
# optional:
# 3 : REPEAT (default True)
from pyformex.gui.menus import Camera
buttons = [["Rotate left", "rotleft", Camera.rotLeft],
["Rotate right", "rotright", Camera.rotRight],
["Rotate up", "rotup", Camera.rotUp],
["Rotate down", "rotdown", Camera.rotDown],
["Twist left", "twistleft", Camera.twistLeft],
["Twist right", "twistright", Camera.twistRight],
["Translate left", "left", Camera.panLeft],
["Translate right", "right", Camera.panRight],
["Translate down", "down", Camera.panDown],
["Translate up", "up", Camera.panUp],
["Zoom Out", "zoomout", Camera.dollyOut],
["Zoom In", "zoomin", Camera.dollyIn],
["Zoom Rectangle", "zoomrect", Camera.zoomRectangle, False],
["Zoom All", "zoomall", Camera.zoomAll, False],
]
for but in buttons:
icon = widgets.pyformexIcon(but[1])
a = toolbar.addAction(icon, but[0], but[2])
b = toolbar.children()[-1] # Get the QToolButton for the last action
if len(but) < 4 or but[3]:
b.setAutoRepeat(True)
b.setAutoRepeatDelay(500)
# This causes a double action on the button click
# only use it if we can detach the button press from trigger
#b.released.connect(a.trigger)
if len(but) >= 5:
# This is currently not used
b.setCheckable(but[4])
b.released.connect(a.toggle)
b.setToolTip(but[0])
#######################################################################
# Viewport Toggle buttons #
###########################
class Toggle(object):
def __init__(self, state=False):
self.state = state
def toggle(self, onoff=None):
if onoff is None:
onoff = not self.state
self.state = onoff
class ViewportToggleButton(object):
def __init__(self, toolbar, tooltip, icon, func, attr, checked=False, icon0=None):
self.button = addButton(toolbar, tooltip, icon, func, toggle=True, icon0=icon0)
self.attr = attr
def updateButton(self):
"""Update the button to current viewport state."""
#print "UPDATE TOGGLE %s" % attr
vp = pf.GUI.viewports.current
if vp == pf.canvas:
self.setChecked(vp.settings[self.attr])
pf.GUI.processEvents()
def toggle(self, attr, state=None):
"""Update the corresponding viewport attribute.
This does not update the button state.
"""
vp = pf.GUI.viewports.current
vp.setToggle(attr, state)
vp.update()
pf.GUI.processEvents()
[docs]def toggleButton(attr, state=None):
"""Update the corresponding viewport attribute.
This does not update the button state.
"""
vp = pf.GUI.viewports.current
vp.setToggle(attr, state)
vp.update()
pf.GUI.processEvents()
[docs]def updateButton(button, attr):
"""Update the button to correct state."""
if button:
vp = pf.GUI.viewports.current
button.setChecked(vp.settings[attr])
pf.GUI.processEvents()
def updateViewportButtons(vp):
## if vp != pf.GUI.viewports.current:
## print "viewport %s is not current" % pf.GUI.viewports.viewIndex(vp)
if vp.focus:
#print "viewport %s has focus" % pf.GUI.viewports.viewIndex(vp)
updateWireButton()
updateTransparencyButton()
updateLightButton()
updateNormalsButton()
#
# BEWARE: The toggle functions are currently not passed the state!
# It should be got from
#
################# Wire Button ###############
wire_button = None # the toggle wire button
def addWireButton(toolbar):
global wire_button
wire_button = addButton(toolbar, 'Toggle Wire Mode',
'wireall', toggleWire, icon0='wirenone',
toggle=True)
def toggleWire(state=None):
vp = pf.GUI.viewports.current
state = wire_button.isChecked()
# TODO:
# WELL, it looks like we get here BEFORE the button is updated,
# so we need to change the state.
# WE should really connect this to a signal that is raised
# AFTER the button state is update
state = not state
vp.setWireMode(state)
vp.update()
pf.GUI.processEvents()
[docs]def updateWireButton():
"""Update the wire button to correct state."""
if wire_button:
vp = pf.GUI.viewports.current
wire_button.setChecked(vp.settings['wiremode'] > 0)
pf.GUI.processEvents()
################# Transparency Button ###############
transparency_button = None # the toggle transparency button
def addTransparencyButton(toolbar):
global transparency_button
transparency_button = addButton(toolbar, 'Toggle Transparent Mode',
'transparent', toggleTransparency,
toggle=True)
def toggleTransparency(state=None):
toggleButton('alphablend', state)
[docs]def updateTransparencyButton():
"""Update the transparency button to correct state."""
updateButton(transparency_button, 'alphablend')
################# Lights Button ###############
light_button = None
def addLightButton(toolbar):
global light_button
light_button = addButton(toolbar, 'Toggle Lights',
'lamp-on', toggleLight, icon0='lamp',
toggle=True, checked=True)
def toggleLight(state=None):
toggleButton('lighting', state)
[docs]def updateLightButton():
"""Update the light button to correct state."""
updateButton(light_button, 'lighting')
################# Normals Button ###############
normals_button = None
def addNormalsButton(toolbar):
global normals_button
normals_button = addButton(toolbar, 'Toggle Normals',
'normals-avg', toggleNormals, icon0='normals-ind',
toggle=True, checked=False)
def toggleNormals(state=None):
toggleButton('avgnormals', state)
[docs]def updateNormalsButton(state=True):
"""Update the normals button to correct state."""
updateButton(normals_button, 'avgnormals')
################# Perspective Button ###############
perspective_button = None # the toggle perspective button
def togglePerspective(mode=None): # Called by the button, not by user
vp = pf.GUI.viewports.current
if mode is None:
mode = not vp.camera.perspective
vp.camera.setPerspective(mode)
vp.display()
vp.update()
pf.GUI.processEvents()
def addPerspectiveButton(toolbar):
global perspective_button
perspective_button = addButton(toolbar, 'Toggle Perspective/Projective Mode',
'perspect', togglePerspective,
toggle=True, icon0='project', checked=True)
[docs]def updatePerspectiveButton():
"""Update the normals button to correct state."""
#updateButton(perspective_button,'avgnormals')
vp = pf.GUI.viewports.current
if vp == pf.canvas:
perspective_button.setChecked(vp.camera.perspective)
pf.GUI.processEvents()
def setPerspective():
togglePerspective(True)
updatePerspectiveButton()
def setProjection():
togglePerspective(False)
updatePerspectiveButton()
################# Shrink Button ###############
#
# The shrink button currently does not redraw, it only sets the default
# shrink factor and clears the viewport
#
shrink_button = None # the toggle shrink button
def toggleShrink(): # Called by the button
from pyformex.gui import draw
mode = draw.DrawOptions.get('shrink', None)
if mode is None:
mode = 0.8
else:
mode = None
draw.shrink(mode)
def addShrinkButton(toolbar):
global shrink_button
shrink_button = addButton(toolbar, 'Toggle Shrink Mode',
'shrink', toggleShrink,
toggle=True)
def setShrink(mode):
from pyformex.gui import draw
draw.shrink(mode)
if shrink_button:
shrink_button.setChecked(mode != None)
################# Timeout Button ###############
timeout_button = None # the timeout toggle button
def toggleTimeout(onoff=None):
if onoff is None:
onoff = widgets.input_timeout < 0
if onoff:
timeout = pf.cfg['gui/timeoutvalue']
else:
timeout = -1
widgets.setInputTimeout(timeout)
onoff = widgets.input_timeout > 0
if onoff:
# THIS SUSPENDS ALL WAITING! WE SHOULD IMPLEMENT A TIMEOUT!
# BY FORCING ALL INDEFINITE PAUSES TO A WAIT TIME EQUAL TO
# WIDGET INPUT TIMEOUT
pf.debug("FREEING the draw lock")
pf.GUI.drawlock.free()
else:
pf.debug("ALLOWING the draw lock")
pf.GUI.drawlock.allow()
return onoff
[docs]def addTimeoutButton(toolbar):
"""Add or remove the timeout button,depending on cfg."""
global timeout_button
if pf.cfg['gui/timeoutbutton']:
if timeout_button is None:
timeout_button = addButton(toolbar, 'Toggle Timeout', 'clock', toggleTimeout, toggle=True, checked=False)
else:
if timeout_button is not None:
removeButton(toolbar, timeout_button)
timeout_button = None
[docs]def timeout(onoff=None):
"""Programmatically toggle the timeout button"""
if timeout_button is not None:
timeout_button.setChecked(toggleTimeout(onoff))
# End