Source code for openalea.oalab.gui.menu
# -*- python -*-
#
# Main Menu class
#
# OpenAlea.OALab: Multi-Paradigm GUI
#
# Copyright 2013 INRIA - CIRAD - INRA
#
# File author(s): Julien Coste <julien.coste@inria.fr>
#
# File contributor(s):
#
# Distributed under the Cecill-C License.
# See accompanying file LICENSE.txt or copy at
# http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html
#
# OpenAlea WebSite : http://openalea.gforge.inria.fr
#
###############################################################################
"""
Full example:
.. code-block:: python
from openalea.vpltk.qt import QtGui
from openalea.oalab.gui.menu import PanedMenu
# Create ribbon bar
menu = PanedMenu()
# Create Qt QAction
act1 = QtGui.QAction(u'act 1', menu)
act2 = QtGui.QAction(u'act 2', menu)
# Add actions to ribbon bar
menu.addBtnByAction('Panel', 'group', act1, PanedMenu.BigButton)
menu.addBtnByAction('Panel', 'group', act2, PanedMenu.SmallButton)
"""
__revision__ = ""
from openalea.vpltk.qt import QtGui, QtCore
"""
# To generate images
from openalea.lpy.gui.compile_ui import check_rc_generation
check_rc_generation('resources.qrc')
"""
size_policy_small = QtGui.QSizePolicy(QtGui.QSizePolicy.Maximum, QtGui.QSizePolicy.Maximum)
big_btn_size = QtCore.QSize(25, 25)
small_btn_size = QtCore.QSize(100, 16)
big_icon_size = QtCore.QSize(24, 24)
small_icon_size = QtCore.QSize(16, 16)
toolbutton_style = """
QToolButton {
background-color: transparent;
min-width: 80px;
}
QToolButton:hover {
border: 1px solid rgb(200, 200, 200);
border-radius: 2px;
}
QToolButton:pressed {
background-color: rgba(0, 0, 0, 50);
border: 1px solid rgb(175, 175, 175);
border-radius: 2px;
}
"""
[docs]class PanedMenu(QtGui.QTabWidget):
"""
A widget that tries to mimic menu of Microsoft Office 2010.
Cf. Ribbon Bar.
>>> from openalea.oalab.gui.menu import PanedMenu
>>> menu = PanedMenu()
"""
BigButton = 0
SmallButton = 1
BigWidget = 'bigwidget'
SmallWidget = 'smallwidget'
def __init__(self, parent=None):
super(PanedMenu, self).__init__()
self.setAccessibleName("Menu")
self.setContentsMargins(0, 0, 0, 0)
size_policy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Maximum)
self.setSizePolicy(size_policy)
self.tab_name = list()
[docs] def addSpecialTab(self, label, widget=None):
widget = Pane()
self.tab_name.append(label)
self.addTab(widget, label)
[docs] def addBtn(self, pane_name, group_name, btn_name, btn_icon, btn_type=0):
"""
:param pane_name: name of pane. type:String.
:param group_name: name of group inside the pane. type:String.
:param btn_name: name of button inside the group. type:String.
:param btn_icon: icon of button. type:QtGui.QIcon.
:param btn_type: type of button to add. 0 = Big Button. 1 = Small Button, smallwidget = Small Widget, bigwidget = Big Widget. Default=0.
:return: created button. type:QToolButton
"""
# Check if pane exist, else create it
if pane_name not in self.tab_name:
self.addSpecialTab(pane_name)
# Get Pane
index = self.tab_name.index(pane_name)
pane = self.widget(index)
# Check if group exist, else create it
if group_name not in pane.group_name:
pane.addGroup(group_name)
# Get group
index = pane.group_name.index(group_name) + 1
grp = pane.layout.itemAtPosition(0, index).widget()
# Add Btn
return grp.addBtn(btn_name, btn_icon, btn_type)
[docs] def addBtnByAction(self, pane_name, group_name, action, btn_type=0):
"""
:param pane_name: name of pane. type:String.
:param group_name: name of group inside the pane. type:String.
:param action: to add (with a name and an icon)
:param btn_type: type of button to add. 0 = Big Button. 1 = Small Button, smallwidget = Small Widget, bigwidget = Big Widget. Default=0.
:return: created button. type:QToolButton
"""
# Check if pane exist, else create it
if pane_name not in self.tab_name:
self.addSpecialTab(pane_name)
# Get Pane
index = self.tab_name.index(pane_name)
pane = self.widget(index)
# Check if group exist, else create it
if group_name not in pane.group_name:
pane.addGroup(group_name)
# Get group
index = pane.group_name.index(group_name) + 1
grp = pane.layout.itemAtPosition(0, index).widget()
# Add Btn
return grp.addBtnByAction(action, btn_type)
[docs] def showPane(self, pane_name):
# Find tab named 'name'
try:
index = self.tab_name.index(pane_name)
except ValueError:
pass
else:
self.setCurrentIndex(index)
[docs]class Pane(QtGui.QWidget):
def __init__(self, parent=None):
# TODO : scroll doesn't work yet
super(Pane, self).__init__()
# self.setWidgetResizable(False)
# self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
# ScrollBarAsNeeded
# ScrollBarAlwaysOn
# ScrollBarAlwaysOff
# self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
self.group_name = list()
self.layout = QtGui.QGridLayout()
self.layout.setContentsMargins(0, 0, 0, 0)
self.layout.setSpacing(0)
self.layout.setAlignment(QtCore.Qt.AlignLeft)
self.setLayout(self.layout)
self.setSizePolicy(size_policy_small)
[docs] def addGroup(self, name):
grp = Group(name)
column = self.layout.columnCount()
self.layout.addWidget(grp, 0, column, QtCore.Qt.AlignHCenter)
self.group_name.append(name)
[docs]class Group(QtGui.QWidget):
def __init__(self, name):
super(Group, self).__init__()
self.setToolTip(name)
self.name = name
self.layout = QtGui.QHBoxLayout()
self.layout.setContentsMargins(0, 0, 0, 0)
self.layout.setSpacing(0)
self.layout.setAlignment(QtCore.Qt.AlignLeft)
self.setLayout(self.layout)
self.layout.addWidget(SubGroupH())
self.layout.addWidget(SubGroupGrid())
# self.setSizePolicy(size_policy_small)
[docs] def addBtnByAction(self, action, style=PanedMenu.BigButton):
if style == PanedMenu.BigButton:
return self.addBigToolButton(action)
elif style == PanedMenu.SmallButton:
return self.addSmallToolButton(action)
elif style == PanedMenu.SmallWidget:
return self.addWidget(action, "small")
elif style == PanedMenu.BigWidget:
return self.addWidget(action, "big")
[docs] def addWidget(self, widget, style="big"):
"""
Permit to add small widget like if it was a small button
"""
btn = widget
if style == "small":
layout = self.layout.itemAt(1).widget().layout
self.check_unicity_group(layout, btn.accessibleName())
column = layout.columnCount()
row = layout.rowCount()
nb = layout.count()
new_row = nb - nb / 3 * 3
# If not a new column
if new_row > 0:
layout.addWidget(btn, new_row + 1, column - 1)
# If new column
else:
layout.addWidget(btn, 1, column)
elif style == "big":
layout = self.layout.itemAt(0).widget().layout
self.check_unicity_box(layout, btn.accessibleName())
layout.addWidget(btn)
return btn
[docs] def addBigBtn(self, name, icon):
btn = BigToolButton(name, icon)
layout = self.layout.itemAt(0).widget().layout
self.check_unicity_box(layout, name)
layout.addWidget(btn)
return btn
[docs] def addSmallBtn(self, name, icon):
btn = SmallToolButton(name, icon)
layout = self.layout.itemAt(1).widget().layout
self.check_unicity_group(layout, name)
column = layout.columnCount()
row = layout.rowCount()
nb = layout.count()
new_row = nb - nb / 3 * 3
# If not a new column
if new_row > 0:
layout.addWidget(btn, new_row + 1, column - 1)
# If new column
else:
layout.addWidget(btn, 1, column)
return btn
[docs] def addBigToolButton(self, action):
btn = BigToolButton(action)
layout = self.layout.itemAt(0).widget().layout
self.check_unicity_box(layout, btn.defaultAction().iconText())
layout.addWidget(btn)
return btn
[docs] def addSmallToolButton(self, action):
btn = SmallToolButton(action)
layout = self.layout.itemAt(1).widget().layout
self.check_unicity_group(layout, btn.defaultAction().iconText())
column = layout.columnCount()
row = layout.rowCount()
nb = layout.count()
new_row = nb - nb / 3 * 3
# If not a new column
if new_row > 0:
layout.addWidget(btn, new_row + 1, column - 1)
# If new column
else:
layout.addWidget(btn, 1, column)
return btn
[docs] def check_unicity_group(self, layout, name):
"""
Hide old button if a new is added with the same name.
Works with groupLayout
"""
column = layout.columnCount()
row = layout.rowCount()
for y in range(column):
for x in range(row):
try:
widget = layout.itemAtPosition(x, y).widget()
if str(widget.text()) == str(name):
widget.hide()
except:
pass
[docs] def check_unicity_box(self, layout, name):
"""
Hide old button if a new is added with the same name
Works with hbox and vbox layout
"""
for i in range(layout.count()):
widget = layout.itemAt(i).widget()
if str(widget.text()) == str(name):
widget.hide()
[docs]class SubGroupH(QtGui.QWidget):
def __init__(self):
super(SubGroupH, self).__init__()
self.layout = QtGui.QHBoxLayout()
self.layout.setContentsMargins(0, 0, 0, 0)
self.layout.setSpacing(0)
self.layout.setAlignment(QtCore.Qt.AlignLeft)
self.setLayout(self.layout)
self.setSizePolicy(size_policy_small)
[docs]class SubGroupV(QtGui.QWidget):
def __init__(self):
super(SubGroupV, self).__init__()
self.layout = QtGui.QVBoxLayout()
self.layout.setContentsMargins(0, 0, 0, 0)
self.layout.setSpacing(0)
self.layout.setAlignment(QtCore.Qt.AlignTop)
self.setLayout(self.layout)
[docs]class SubGroupGrid(QtGui.QWidget):
def __init__(self):
super(SubGroupGrid, self).__init__()
self.layout = QtGui.QGridLayout()
self.layout.setContentsMargins(0, 0, 0, 0)
self.layout.setSpacing(0)
self.layout.setAlignment(QtCore.Qt.AlignLeft)
self.setLayout(self.layout)
[docs]class ToolButton(QtGui.QToolButton):
def __init__(self, action, icon=None):
super(ToolButton, self).__init__()
self.setAutoRaise(True)
if isinstance(action, QtGui.QAction):
self.setDefaultAction(action)
else:
self.setText(str(action))
if isinstance(icon, QtGui.QIcon):
self.setIcon(icon)
self.setStyleSheet(toolbutton_style)
self.setSizePolicy(size_policy_small)
self.setContentsMargins(0, 0, 0, 0)
[docs]class BigToolButton(ToolButton):
def __init__(self, action, icon=None):
super(BigToolButton, self).__init__(action, icon)
self.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly)
self.setIconSize(big_icon_size)
self.setMinimumSize(big_btn_size)
self.setMaximumSize(big_btn_size)
[docs]class SmallToolButton(ToolButton):
def __init__(self, action, icon=None):
super(SmallToolButton, self).__init__(action, icon)
self.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)
self.setIconSize(small_icon_size)
self.setMinimumSize(small_btn_size)
self.setMaximumSize(small_btn_size)
if __name__ == '__main__':
import sys
from openalea.vpltk.qt import QtGui
instance = QtGui.QApplication.instance()
if instance is None:
qapp = QtGui.QApplication(sys.argv)
else:
qapp = instance
# Example: create a panel with one group containing 1 big and 3 small buttons
menu = PanedMenu()
act0 = QtGui.QAction(u'Action', menu)
act1 = QtGui.QAction(u'act 1', menu)
act2 = QtGui.QAction(u'act 2', menu)
act3 = QtGui.QAction(u'act 3', menu)
menu.addBtnByAction('Panel', 'group', act0, PanedMenu.BigButton)
menu.addBtnByAction('Panel', 'group', act1, PanedMenu.SmallButton)
menu.addBtnByAction('Panel', 'group', act2, PanedMenu.SmallButton)
menu.addBtnByAction('Panel', 'group', act3, PanedMenu.SmallButton)
menu.show()
if instance is None:
qapp.exec_()