Source code for enaml.qt.qt_main_window

#------------------------------------------------------------------------------
#  Copyright (c) 2012, Enthought, Inc.
#  All rights reserved.
#------------------------------------------------------------------------------
import sys

from .qt.QtCore import Qt, Signal
from .qt.QtGui import QMainWindow
from .q_deferred_caller import deferredCall
from .qt_container import QtContainer
from .qt_dock_pane import QtDockPane
from .qt_menu_bar import QtMenuBar
from .qt_tool_bar import QtToolBar
from .qt_window import QtWindow


class QCustomMainWindow(QMainWindow):
    """ A custom QMainWindow which adds some Enaml specific features.

    """
    #: A signal emitted when the window is closed by the user
    closed = Signal()

    #--------------------------------------------------------------------------
    # Private API
    #--------------------------------------------------------------------------
    def closeEvent(self, event):
        """ A close event handler which emits the 'closed' signal.

        """
        super(QCustomMainWindow, self).closeEvent(event)
        self.closed.emit()

    #--------------------------------------------------------------------------
    # Public API
    #--------------------------------------------------------------------------
    def setDockWidgetArea(self, area, dock_widget):
        """ Set the dock area for the given dock widget.

        If the dock widget has not been added to the main window, this
        method is a no-op.

        Parameters
        ----------
        area : QDockWidgetArea
            The dock area to use for the widget.

        dock_widget : QDockWidget
            The dock widget to move to the given area.

        """
        curr = self.dockWidgetArea(dock_widget)
        if curr != Qt.NoDockWidgetArea:
            if curr != area:
                visible = dock_widget.isVisible()
                self.removeDockWidget(dock_widget)
                self.addDockWidget(area, dock_widget)
                dock_widget.setVisible(visible)

    def setToolBarArea(self, area, tool_bar):
        """ Set the tool bar area for the given tool bar.

        If the tool bar has not been added to the main window, this
        method is a no-op.

        Parameters
        ----------
        area : QToolBarArea
            The tool bar area to use for the widget.

        tool_bar : QToolBar
            The tool bar to move to the given area.

        """
        curr = self.toolBarArea(tool_bar)
        if curr != Qt.NoToolBarArea:
            if curr != area:
                visible = tool_bar.isVisible()
                floating = tool_bar.isFloating()
                tool_bar.setVisible(False)
                self.removeToolBar(tool_bar)
                self.addToolBar(area, tool_bar)
                tool_bar.resize(tool_bar.sizeHint())
                tool_bar.setFloating(floating)
                tool_bar.setVisible(visible)


[docs]class QtMainWindow(QtWindow): """ A Qt implementation of an Enaml MainWindow. """ #: A private flag used to track the visible state changes sent from #: the Enaml widget. This is needed on OSX when dynamically adding #: a tool bar in order to work around a visibility bug in Qt. _visible_hint = False #-------------------------------------------------------------------------- # Setup Methods #--------------------------------------------------------------------------
[docs] def create_widget(self, parent, tree): """ Create the underlying widget QMainWindow widget. """ widget = QCustomMainWindow(parent) widget.setDocumentMode(True) widget.setDockNestingEnabled(True) return widget
[docs] def init_layout(self): """ Initialize the layout for the underlying widget. """ # The superclass' init_layout() method is explicitly not called # since the layout initialization for Window is not appropriate # for MainWindow. main_window = self.widget() components = self.components() main_window.setMenuBar(components['menu_bar']) main_window.setCentralWidget(components['central_widget']) for dpane in components['dock_panes']: main_window.addDockWidget(dpane.dockArea(), dpane) for tbar in components['tool_bars']: # XXX slight hack. When adding the toolbar to the main # window, it is forcibly unfloated. In order for the # initial floating state to be maintained, it must be # re-floating after being added. We do the refloating # in the future, so that the main window shows up first. floating = tbar.isFloating() main_window.addToolBar(tbar.toolBarArea(), tbar) if floating: deferredCall(tbar.setFloating, True) #-------------------------------------------------------------------------- # Utility Methods #--------------------------------------------------------------------------
[docs] def components(self): """ Get a dictionary of the main window components. Returns ------- result : dict A dicionary of main window components categorized by their function. """ d = { 'central_widget': None, 'menu_bar': None, 'tool_bars': [], 'dock_panes': [], } for child in self.children(): if isinstance(child, QtDockPane): d['dock_panes'].append(child.widget()) elif isinstance(child, QtToolBar): d['tool_bars'].append(child.widget()) elif isinstance(child, QtMenuBar): d['menu_bar'] = child.widget() elif isinstance(child, QtContainer): d['central_widget'] = child.widget() return d #-------------------------------------------------------------------------- # Child Events #--------------------------------------------------------------------------
[docs] def child_removed(self, child): """ Handle the child removed event for a QtMainWindow. """ main_window = self.widget() if isinstance(child, QtDockPane): main_window.removeDockWidget(child.widget()) elif isinstance(child, QtToolBar): main_window.removeToolBar(child.widget()) elif isinstance(child, QtContainer): components = self.components() main_window.setCentralWidget(components['central_widget']) elif isinstance(child, QtMenuBar): components = self.components() main_window.setMenuBar(components['menu_bar'])
[docs] def child_added(self, child): """ Handle the child added event for a QtMainWindow. """ main_window = self.widget() if isinstance(child, QtMenuBar): components = self.components() main_window.setMenuBar(components['menu_bar']) elif isinstance(child, QtContainer): components = self.components() main_window.setCentralWidget(components['central_widget']) elif isinstance(child, QtDockPane): dock_widget = child.widget() main_window.addDockWidget(dock_widget.dockArea(), dock_widget) elif isinstance(child, QtToolBar): # There are two hacks involved in adding a tool bar. The # first is the same hack that is perfomed in the layout # method for a floating tool bar. The second is specific # to OSX. On that platform, adding a tool bar to main # window which is already visible but does not have any # current tool bars will cause the main window to be hidden. # This will only occur the *first* time a tool bar is added # to the window. The hack below is workaround which should # be sufficient for most use cases. A bug should really be # filed against Qt for this one, since it's reproducible # outside of Enaml. bar_widget = child.widget() reshow = False if sys.platform == 'darwin': reshow = self._visible_hint and not main_window.isVisible() floating = bar_widget.isFloating() main_window.addToolBar(bar_widget.toolBarArea(), bar_widget) if floating: deferredCall(bar_widget.setFloating, True) if reshow: main_window.setVisible(True) #-------------------------------------------------------------------------- # Widget Update Methods #--------------------------------------------------------------------------
[docs] def set_visible(self, visible): """ Set the visibility of the underlying control. This is an overridden parent class method which keeps track of the visible flag set by the Enaml widget. """ self._visible_hint = visible super(QtMainWindow, self).set_visible(visible)