manuskript/manuskript/ui/collapsibleDockWidgets.py

159 lines
5.7 KiB
Python
Raw Normal View History

2015-07-10 01:01:07 +12:00
#!/usr/bin/env python
2016-02-07 00:34:22 +13:00
# --!-- coding: utf8 --!--
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QToolBar, QDockWidget, QAction, QToolButton, QSizePolicy, QStylePainter, \
2016-03-25 01:42:47 +13:00
QStyleOptionButton, QStyle
2015-07-10 01:01:07 +12:00
from manuskript.ui import style
2015-07-10 01:01:07 +12:00
class collapsibleDockWidgets(QToolBar):
"""
QMainWindow "mixin" which provides auto-hiding support for dock widgets
(not toolbars).
"""
TRANSPOSED_AREA = {
Qt.LeftDockWidgetArea: Qt.LeftToolBarArea,
Qt.RightDockWidgetArea: Qt.RightToolBarArea,
Qt.TopDockWidgetArea: Qt.TopToolBarArea,
Qt.BottomDockWidgetArea: Qt.BottomToolBarArea,
2016-02-07 00:34:22 +13:00
}
2015-07-10 01:01:07 +12:00
def __init__(self, area, parent, name=""):
QToolBar.__init__(self, parent)
self._area = area
if not name:
name = self.tr("Dock Widgets Toolbar")
self.setObjectName(name)
self.setWindowTitle(name)
self.setFloatable(False)
self.setMovable(False)
2016-02-07 00:34:22 +13:00
# self.setAllowedAreas(self.TRANSPOSED_AREA[self._area])
2015-07-10 01:01:07 +12:00
self.parent().addToolBar(self.TRANSPOSED_AREA[self._area], self)
2016-02-07 00:34:22 +13:00
2016-03-25 01:42:47 +13:00
self._dockToButtonAction = {}
2015-07-10 01:01:07 +12:00
# Dock widgets
for d in self._dockWidgets():
b = verticalButton(self)
b.setDefaultAction(d.toggleViewAction())
2016-02-08 22:30:32 +13:00
# d.setStyleSheet("QDockWidget::title{background-color: red;}")
# d.setTitleBarWidget(QLabel(d.windowTitle()))
d.setStyleSheet(style.dockSS())
2016-03-25 01:42:47 +13:00
a = self.addWidget(b)
self._dockToButtonAction[d] = a
2016-02-07 00:34:22 +13:00
2015-07-10 01:01:07 +12:00
self.addSeparator()
2016-02-07 00:34:22 +13:00
2015-07-10 01:01:07 +12:00
# Other widgets
self.otherWidgets = []
self.currentGroup = None
self.setStyleSheet(style.toolBarSS())
2017-12-01 05:18:53 +13:00
self.layout().setContentsMargins(0,0,0,0)
2015-07-10 01:01:07 +12:00
def _dockWidgets(self):
mw = self.parent()
for w in mw.findChildren(QDockWidget, None):
yield w
def addCustomWidget(self, text, widget, group=None, defaultVisibility=True):
"""
Adds a custom widget to the toolbar.
2017-12-01 05:18:53 +13:00
`text` is the name that will displayed on the button to switch visibility.
`widget` is the widget to control from the toolbar.
`group` is an integer (or any hashable) if the current widget should not
be displayed all the time. Call `collapsibleDockWidgets.setCurrentGroup`
to switch to that group and hide other widgets.
`defaultVisibility` is the default visibility of the item when it is added.
This allows for the widget to be added to `collapsibleDockWidgets` after
they've been created but before they are shown, and yet specify their
desired visibility. Otherwise it creates troubles, see #167 on github:
https://github.com/olivierkes/manuskript/issues/167.
"""
2015-07-10 01:01:07 +12:00
a = QAction(text, self)
a.setCheckable(True)
a.setChecked(defaultVisibility)
2015-07-10 01:01:07 +12:00
a.toggled.connect(widget.setVisible)
widget.setVisible(defaultVisibility)
2016-02-07 00:34:22 +13:00
# widget.installEventFilter(self)
2015-07-10 01:01:07 +12:00
b = verticalButton(self)
b.setDefaultAction(a)
#b.setChecked(widget.isVisible())
2015-07-10 01:01:07 +12:00
a2 = self.addWidget(b)
self.otherWidgets.append((b, a2, widget, group))
2016-02-07 00:34:22 +13:00
# def eventFilter(self, widget, event):
# if event.type() in [QEvent.Show, QEvent.Hide]:
# for btn, action, w, grp in self.otherWidgets:
# if w == widget:
# btn.defaultAction().setChecked(event.type() == QEvent.Show)
# return False
def switchActionByWidget(self, widget, visibility=True):
for _btn, _action, _widget, _grp in self.otherWidgets:
if widget == _widget:
_btn.setChecked(visibility)
2015-07-10 01:01:07 +12:00
def setCurrentGroup(self, group):
self.currentGroup = group
for btn, action, widget, grp in self.otherWidgets:
2021-02-22 11:45:34 +13:00
if not grp == group or grp == None:
2015-07-10 01:01:07 +12:00
action.setVisible(False)
else:
action.setVisible(True)
2016-02-07 00:34:22 +13:00
2016-03-25 01:42:47 +13:00
def setDockVisibility(self, dock, val):
dock.setVisible(val)
self._dockToButtonAction[dock].setVisible(val)
def saveState(self):
"""
Saves and returns the state of the custom widgets. The visibility of the
docks is not saved since it is included in `QMainWindow.saveState`.
"""
state = []
for btn, act, w, grp in self.otherWidgets:
state.append(
(grp, btn.text(), btn.isChecked())
)
return state
def restoreState(self, state):
"""Restores the state of the custom widgets."""
for group, title, status in state:
for btn, act, widget, grp in self.otherWidgets:
# Strip '&' from both title and btn.text() to improve matching because
# title contains "&" shortcut character whereas btn.text() does not.
if group == grp and title.replace('&', '') == btn.text().replace('&', ''):
btn.setChecked(status)
btn.defaultAction().setChecked(status)
widget.setVisible(status)
2015-07-10 01:01:07 +12:00
class verticalButton(QToolButton):
def __init__(self, parent):
QToolButton.__init__(self, parent)
self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Minimum)
2016-02-07 00:34:22 +13:00
self.setStyleSheet(style.verticalToolButtonSS())
2015-07-10 01:01:07 +12:00
def sizeHint(self):
return QToolButton.sizeHint(self).transposed()
2016-02-07 00:34:22 +13:00
2015-07-10 01:01:07 +12:00
def paintEvent(self, event):
p = QStylePainter(self)
p.rotate(90)
p.translate(0, - self.width())
opt = QStyleOptionButton()
opt.initFrom(self)
opt.text = self.text()
if self.isChecked():
opt.state |= QStyle.State_On
s = opt.rect.size().transposed()
opt.rect.setSize(s)
2016-02-07 00:34:22 +13:00
p.drawControl(QStyle.CE_PushButton, opt)