#------------------------------------------------------------------------------
# Copyright (c) 2012, Enthought, Inc.
# All rights reserved.
#------------------------------------------------------------------------------
from .qt.QtCore import Qt, Signal
from .qt.QtGui import QDockWidget, QWidget
from .qt_container import QtContainer
from .qt_widget import QtWidget
#: A mapping from Enaml dock areas to Qt dock areas.
_DOCK_AREA_MAP = {
'top': Qt.TopDockWidgetArea,
'right': Qt.RightDockWidgetArea,
'bottom': Qt.BottomDockWidgetArea,
'left': Qt.LeftDockWidgetArea,
'all': Qt.AllDockWidgetAreas,
}
#: A mapping from Qt dock areas to Enaml dock areas.
_DOCK_AREA_INV_MAP = {
Qt.TopDockWidgetArea: 'top',
Qt.RightDockWidgetArea: 'right',
Qt.BottomDockWidgetArea: 'bottom',
Qt.LeftDockWidgetArea: 'left',
Qt.AllDockWidgetAreas: 'all',
}
class QCustomDockWidget(QDockWidget):
""" A custom QDockWidget which adds some Enaml specific features.
"""
#: A signal emitted when the dock widget is closed by the user.
closed = Signal()
#: A signal emitted when the dock widget is floated.
floated = Signal()
#: A signal emitted when the dock widget is docked. The payload
#: will be the new dock area.
docked = Signal(object)
def __init__(self, *args, **kwargs):
""" Initialize a QCustomDockWidget.
Parameters
----------
*args, **kwargs
The positional and keyword arguments needed to initialize
a QDockWidget.
"""
super(QCustomDockWidget, self).__init__(*args, **kwargs)
self._title_bar_visible = True
self._dock_area = Qt.LeftDockWidgetArea
self.topLevelChanged.connect(self._onTopLevelChanged)
#--------------------------------------------------------------------------
# Private API
#--------------------------------------------------------------------------
def _onTopLevelChanged(self, top_level):
""" The signal handler for the the 'topLevelChanged' signal.
"""
# Hiding the title bar on a floating dock widget causes the
# frame to be hidden. We need to make sure its shown when
# floating, and hidden again upon docking if needed.
if top_level:
self._showTitleBar()
self.floated.emit()
else:
if not self._title_bar_visible:
self._hideTitleBar()
parent = self.parent()
if parent is not None:
self._dock_area = parent.dockWidgetArea(self)
self.docked.emit(self._dock_area)
def _showTitleBar(self):
""" Shows the title bar for the widget.
"""
if self.titleBarWidget() is not None:
self.setTitleBarWidget(None)
def _hideTitleBar(self):
""" Hides the title bar for the widget.
"""
if self.titleBarWidget() is None:
self.setTitleBarWidget(QWidget())
def closeEvent(self, event):
""" A close event handler which emits the 'closed' signal.
"""
super(QCustomDockWidget, self).closeEvent(event)
self.closed.emit()
#--------------------------------------------------------------------------
# Public API
#--------------------------------------------------------------------------
def dockArea(self):
""" Get the current dock area for the dock widget.
Returns
-------
result : QDockWidgetArea
The dock widget area where this dock widget resides.
"""
return self._dock_area
def setDockArea(self, area):
""" Set the current dock area for the dock widget.
Parameters
----------
area : QDockWidgetArea
The dock widget area where this dock widget should reside.
"""
self._dock_area = area
parent = self.parent()
if parent is not None:
parent.setDockWidgetArea(area, self)
def titleBarVisible(self):
""" Get whether or not the title bar is visible.
Returns
-------
result : bool
Whether or not the title bar is visible.
"""
return self._title_bar_visible
def setTitleBarVisible(self, visible):
""" Set whether or not the title bar is visible.
Parameters
----------
visible : bool
Whether or not the title bar is visible.
"""
self._title_bar_visible = visible
if visible:
self._showTitleBar()
else:
if not self.isFloating():
self._hideTitleBar()
[docs]class QtDockPane(QtWidget):
""" A Qt implementation of an Enaml DockPane.
"""
#--------------------------------------------------------------------------
# Setup Methods
#--------------------------------------------------------------------------
[docs] def create(self, tree):
""" Create and initialize the dock pane control.
"""
super(QtDockPane, self).create(tree)
self.set_title(tree['title'])
self.set_title_bar_visible(tree['title_bar_visible'])
self.set_title_bar_orientation(tree['title_bar_orientation'])
self.set_closable(tree['closable'])
self.set_movable(tree['movable'])
self.set_floatable(tree['floatable'])
self.set_floating(tree['floating'])
self.set_dock_area(tree['dock_area'])
self.set_allowed_dock_areas(tree['allowed_dock_areas'])
widget = self.widget()
widget.closed.connect(self.on_closed)
widget.floated.connect(self.on_floated)
widget.docked.connect(self.on_docked)
[docs] def init_layout(self):
""" Handle the layout initialization for the dock pane.
"""
super(QtDockPane, self).init_layout()
self.widget().setWidget(self.dock_widget())
#--------------------------------------------------------------------------
# Utility Methods
#--------------------------------------------------------------------------
[docs] def child_removed(self, child):
""" Handle the child removed event for a QtDockPane.
"""
if isinstance(child, QtContainer):
self.widget().setWidget(self.dock_widget())
[docs] def child_added(self, child):
""" Handle the child added event for a QtDockPane.
"""
if isinstance(child, QtContainer):
self.widget().setWidget(self.dock_widget())
#--------------------------------------------------------------------------
# Signal Handlers
#--------------------------------------------------------------------------
[docs] def on_closed(self):
""" The signal handler for the 'closed' signal.
"""
# The closed signal is only emitted when the widget is closed
# by the user, so there is no need for a loopback guard.
self.send_action('closed', {})
[docs] def on_floated(self):
""" The signal handler for the 'floated' signal.
"""
if 'floating' not in self.loopback_guard:
self.send_action('floated', {})
[docs] def on_docked(self, area):
""" The signal handler for the 'docked' signal.
"""
if 'floating' not in self.loopback_guard:
content = {'dock_area': _DOCK_AREA_INV_MAP[area]}
self.send_action('docked', content)
#--------------------------------------------------------------------------
# Message Handling
#--------------------------------------------------------------------------
[docs] def on_action_set_title(self, content):
""" Handle the 'set_title' action from the Enaml widget.
"""
self.set_title(content['title'])
[docs] def on_action_set_title_bar_visible(self, content):
""" Handle the 'set_title_bar_visible' action from the Enaml
widget.
"""
self.set_title_bar_visible(content['title_bar_visible'])
[docs] def on_action_set_title_bar_orientation(self, content):
""" Handle the 'set_title_bar_orientation' action from the
Enaml widget.
"""
self.set_title_bar_orientation(content['title_bar_orientation'])
[docs] def on_action_set_closable(self, content):
""" Handle the 'set_closable' action from the Enaml widget.
"""
self.set_closable(content['closable'])
[docs] def on_action_set_movable(self, content):
""" Handle the 'set_movable' action from the Enaml widget.
"""
self.set_movable(content['movable'])
[docs] def on_action_set_floatable(self, content):
""" Handle the 'set_floatable' action from the Enaml widget.
"""
self.set_floatable(content['floatable'])
[docs] def on_action_set_floating(self, content):
""" Handle the 'set_floating' action from the Enaml widget.
"""
self.set_floating(content['floating'])
[docs] def on_action_set_dock_area(self, content):
""" Handle the 'set_dock_area' action from the Enaml widget.
"""
self.set_dock_area(content['dock_area'])
[docs] def on_action_set_allowed_dock_areas(self, content):
""" Handle the 'set_allowed_dock_areas' action from the Enaml
widget.
"""
self.set_allowed_dock_areas(content['allowed_dock_areas'])
[docs] def on_action_open(self, content):
""" Handle the 'open' action from the Enaml widget.
"""
self.widget().setVisible(True)
[docs] def on_action_close(self, content):
""" Handle the 'close' action from the Enaml widget.
"""
# Don't call widget.close() since that will fire a closeEvent.
self.widget().setVisible(False)
#--------------------------------------------------------------------------
# Widget Update Methods
#--------------------------------------------------------------------------
[docs] def set_title(self, title):
""" Set the title on the underlying widget.
"""
self.widget().setWindowTitle(title)
[docs] def set_title_bar_visible(self, visible):
""" Set the title bar visibility of the underlying widget.
"""
self.widget().setTitleBarVisible(visible)
[docs] def set_title_bar_orientation(self, orientation):
""" Set the title bar orientation of the underyling widget.
"""
widget = self.widget()
features = widget.features()
if orientation == 'vertical':
features |= QDockWidget.DockWidgetVerticalTitleBar
else:
features &= ~QDockWidget.DockWidgetVerticalTitleBar
widget.setFeatures(features)
[docs] def set_closable(self, closable):
""" Set the closable state on the underlying widget.
"""
widget = self.widget()
features = widget.features()
if closable:
features |= QDockWidget.DockWidgetClosable
else:
features &= ~QDockWidget.DockWidgetClosable
widget.setFeatures(features)
[docs] def set_movable(self, movable):
""" Set the movable state on the underlying widget.
"""
widget = self.widget()
features = widget.features()
if movable:
features |= QDockWidget.DockWidgetMovable
else:
features &= ~QDockWidget.DockWidgetMovable
widget.setFeatures(features)
[docs] def set_floatable(self, floatable):
""" Set the floatable state on the underlying widget.
"""
widget = self.widget()
features = widget.features()
if floatable:
features |= QDockWidget.DockWidgetFloatable
else:
features &= ~QDockWidget.DockWidgetFloatable
widget.setFeatures(features)
[docs] def set_floating(self, floating):
""" Set the floating staet on the underlying widget.
"""
with self.loopback_guard('floating'):
self.widget().setFloating(floating)
[docs] def set_dock_area(self, dock_area):
""" Set the dock area on the underlying widget.
"""
self.widget().setDockArea(_DOCK_AREA_MAP[dock_area])
[docs] def set_allowed_dock_areas(self, dock_areas):
""" Set the allowed dock areas on the underlying widget.
"""
qt_areas = Qt.NoDockWidgetArea
for area in dock_areas:
qt_areas |= _DOCK_AREA_MAP[area]
self.widget().setAllowedAreas(qt_areas)