Пример #1
0
    def __init__(self, parent=None, position=QDockBar.North):
        """ Initialize a QDockBarItem.

        Parameters
        ----------
        parent : QWidget, optional
            The parent of the dock bar item.

        position : QDockBar.Position, optional
            The position of the dock bar for the item.

        """
        super(QDockBarItem, self).__init__(parent)
        assert isinstance(position, QDockBar.Position)
        self.setProperty('position', int(position))
        self._user_size = QSize()
        self._animation = None
        self._widget = None
        handle = QDockBarItemHandle()
        handle.handleMoved.connect(self._onHandleMoved)
        if position == QDockBar.North or position == QDockBar.South:
            layout = QVBoxLayout()
            handle.setCursor(Qt.SizeVerCursor)
        else:
            layout = QHBoxLayout()
            handle.setCursor(Qt.SizeHorCursor)
        layout.addWidget(handle, 0)
        layout.setSpacing(0)
        layout.setContentsMargins(QMargins(0, 0, 0, 0))
        layout.setSizeConstraint(QLayout.SetMinimumSize)
        self.setLayout(layout)
Пример #2
0
    def __init__(self, parent=None):
        """ Initialize a QDockWindowButtons instance.

        Parameters
        ----------
        parent : QWidget, optional
            The parent of the window buttons.

        """
        super(QDockWindowButtons, self).__init__(parent)
        self._buttons = (
            self.CloseButton | self.MaximizeButton | self.LinkButton
        )

        max_button = self._max_button = QBitmapButton(self)
        max_button.setObjectName('dockwindow-maximize-button')
        max_button.setBitmap(MAXIMIZE_BUTTON.toBitmap())
        max_button.setIconSize(QSize(20, 15))
        max_button.setVisible(self._buttons & self.MaximizeButton)
        max_button.setToolTip('Maximize')

        restore_button = self._restore_button = QBitmapButton(self)
        restore_button.setObjectName('dockwindow-restore-button')
        restore_button.setBitmap(RESTORE_BUTTON.toBitmap())
        restore_button.setIconSize(QSize(20, 15))
        restore_button.setVisible(self._buttons & self.RestoreButton)
        restore_button.setToolTip('Restore Down')

        close_button = self._close_button = QBitmapButton(self)
        close_button.setObjectName('dockwindow-close-button')
        close_button.setBitmap(CLOSE_BUTTON.toBitmap())
        close_button.setIconSize(QSize(34, 15))
        close_button.setVisible(self._buttons & self.CloseButton)
        close_button.setToolTip('Close')

        link_button = self._link_button = QCheckedBitmapButton(self)
        link_button.setObjectName('dockwindow-link-button')
        link_button.setBitmap(UNLINKED_BUTTON.toBitmap())
        link_button.setCheckedBitmap(LINKED_BUTTON.toBitmap())
        link_button.setIconSize(QSize(20, 15))
        link_button.setVisible(self._buttons & self.LinkButton)
        link_button.setToolTip('Link Window')
        link_button.setCheckedToolTip('Unlink Window')

        layout = QHBoxLayout()
        layout.setContentsMargins(QMargins(0, 0, 0, 0))
        layout.setSpacing(1)

        layout.addWidget(link_button)
        layout.addWidget(max_button)
        layout.addWidget(restore_button)
        layout.addWidget(close_button)

        self.setLayout(layout)

        max_button.clicked.connect(self.maximizeButtonClicked)
        restore_button.clicked.connect(self.restoreButtonClicked)
        close_button.clicked.connect(self.closeButtonClicked)
        link_button.toggled.connect(self.linkButtonToggled)
Пример #3
0
    def resizeMargins(self):
        """ Get the margins to use for resizing the frame.

        Returns
        -------
        result : QMargins
            The margins to use for frame resizing when the frame is
            a top-level window.

        """
        return QMargins()
Пример #4
0
    def __init__(self, parent=None):
        """ Initialize a QDockArea.

        Parameters
        ----------
        parent : QWidget
            The parent of the dock area.

        """
        super(QDockArea, self).__init__(parent)
        self._dock_bar_manager = QDockBarManager(self)
        self._primary_pane = primary_pane = QWidget(self)
        self._central_pane = central_pane = QWidget(primary_pane)
        self._dock_events_enabled = False
        self._opaque_resize = None
        self._tab_position = None

        central_layout = QVBoxLayout()
        central_layout.setContentsMargins(QMargins(0, 0, 0, 0))
        central_layout.setSizeConstraint(QLayout.SetMinimumSize)
        central_pane.setLayout(central_layout)

        grid_layout = QGridLayout()
        grid_layout.setRowStretch(0, 0)
        grid_layout.setRowStretch(1, 1)
        grid_layout.setRowStretch(2, 0)
        grid_layout.setColumnStretch(0, 0)
        grid_layout.setColumnStretch(1, 1)
        grid_layout.setColumnStretch(2, 0)
        grid_layout.setContentsMargins(QMargins(0, 0, 0, 0))
        grid_layout.setSizeConstraint(QLayout.SetMinimumSize)
        grid_layout.addWidget(central_pane, 1, 1)
        primary_pane.setLayout(grid_layout)

        area_layout = QDockAreaLayout()
        area_layout.setContentsMargins(QMargins(0, 0, 0, 0))
        area_layout.setSizeConstraint(QLayout.SetMinimumSize)
        area_layout.insertWidget(0, primary_pane)
        self.setLayout(area_layout)
        self.updateSpacing()
Пример #5
0
    def resizeMargins(self):
        """ Get the margins to use for resizing the container.

        Returns
        -------
        result : QMargins
            The margins to use for container resizing when the container
            is a top-level window.

        """
        if self.isMaximized():
            return QMargins()
        return self.ResizeMargins
Пример #6
0
    def unfloat(self):
        """ Set the window state to be non-floating window.

        """
        self.hide()
        self.setAttribute(Qt.WA_Hover, False)
        self.setParent(self.manager().dock_area(), Qt.Widget)
        self.layout().setContentsMargins(QMargins(0, 0, 0, 0))
        self.unsetCursor()
        self.setProperty('floating', False)
        self.setLinked(False)
        self.hideLinkButton()
        self.showPinButton()
        repolish(self)
        self.topLevelChanged.emit(False)
Пример #7
0
    def float(self):
        """ Set the window state to be a toplevel floating window.

        """
        self.hide()
        self.setAttribute(Qt.WA_Hover, True)
        flags = Qt.Tool | Qt.FramelessWindowHint
        self.setParent(self.manager().dock_area(), flags)
        self.layout().setContentsMargins(QMargins(5, 5, 5, 5))
        self.setProperty('floating', True)
        self.setLinked(False)
        self.showLinkButton()
        self.hidePinButton()
        repolish(self)
        self.topLevelChanged.emit(True)
Пример #8
0
    def __init__(self, parent=None, position=Position.North):
        """ Initialize a QDockBar.

        Parameters
        ----------
        parent : QWidget, optional
            The parent widget of the dock bar.

        position : QDockBar.Position, optional
            The position enum value for the dock bar. This dictates the
            layout and orientation of the contained dock buttons. The
            default position is QDockBar.North.

        """
        super(QDockBar, self).__init__(parent)
        assert isinstance(position, QDockBar.Position)
        self.setProperty('position', int(position))
        layout = QBoxLayout(self.LayoutPositions[position])
        layout.setContentsMargins(QMargins(0, 0, 0, 0))
        layout.addStretch(1)
        self.setLayout(layout)
        self.updateSpacing()
Пример #9
0
    def __init__(self, parent=None):
        """ Initialize a QDockTitleBar.

        Parameters
        ----------
        parent : QWidget or None
            The parent of the title bar.

        """
        super(QDockTitleBar, self).__init__(parent)
        self._buttons = self.CloseButton | self.MaximizeButton | self.PinButton
        self._is_editable = False
        self._force_hidden = False
        self._last_visible = True
        self._line_edit = None

        title_icon = self._title_icon = QIconWidget(self)
        title_icon.setVisible(False)

        title_label = self._title_label = QTextLabel(self)

        spacer = self._spacer = QWidget(self)
        policy = spacer.sizePolicy()
        policy.setHorizontalPolicy(QSizePolicy.Expanding)
        spacer.setSizePolicy(policy)

        btn_size = QSize(14, 13)

        max_button = self._max_button = QBitmapButton(self)
        max_button.setObjectName('docktitlebar-maximize-button')
        max_button.setBitmap(MAXIMIZE_BUTTON.toBitmap())
        max_button.setIconSize(btn_size)
        max_button.setVisible(self._buttons & self.MaximizeButton)
        max_button.setToolTip('Maximize')

        restore_button = self._restore_button = QBitmapButton(self)
        restore_button.setObjectName('docktitlebar-restore-button')
        restore_button.setBitmap(RESTORE_BUTTON.toBitmap())
        restore_button.setIconSize(btn_size)
        restore_button.setVisible(self._buttons & self.RestoreButton)
        restore_button.setToolTip('Restore Down')

        close_button = self._close_button = QBitmapButton(self)
        close_button.setObjectName('docktitlebar-close-button')
        close_button.setBitmap(CLOSE_BUTTON.toBitmap())
        close_button.setIconSize(btn_size)
        close_button.setVisible(self._buttons & self.CloseButton)
        close_button.setToolTip('Close')

        link_button = self._link_button = QCheckedBitmapButton(self)
        link_button.setObjectName('docktitlebar-link-button')
        link_button.setBitmap(UNLINKED_BUTTON.toBitmap())
        link_button.setCheckedBitmap(LINKED_BUTTON.toBitmap())
        link_button.setIconSize(btn_size)
        link_button.setVisible(self._buttons & self.LinkButton)
        link_button.setToolTip('Link Window')
        link_button.setCheckedToolTip('Unlink Window')

        pin_button = self._pin_button = QCheckedBitmapButton(self)
        pin_button.setObjectName('docktitlebar-pin-button')
        pin_button.setBitmap(PIN_BUTTON.toBitmap())
        pin_button.setCheckedBitmap(UNPIN_BUTTON.toBitmap())
        pin_button.setIconSize(QSize(13, 13))
        pin_button.setVisible(self._buttons & self.PinButton)
        pin_button.setToolTip('Pin Window')
        pin_button.setCheckedToolTip('Unpin Window')

        layout = QHBoxLayout()
        layout.setContentsMargins(QMargins(5, 2, 5, 2))
        layout.setSpacing(1)
        layout.addWidget(title_icon)
        layout.addSpacing(0)
        layout.addWidget(title_label)
        layout.addWidget(spacer)
        layout.addSpacing(4)
        layout.addWidget(pin_button)
        layout.addWidget(link_button)
        layout.addWidget(max_button)
        layout.addWidget(restore_button)
        layout.addWidget(close_button)

        self.setLayout(layout)

        max_button.clicked.connect(self.maximizeButtonClicked)
        restore_button.clicked.connect(self.restoreButtonClicked)
        close_button.clicked.connect(self.closeButtonClicked)
        link_button.toggled.connect(self.linkButtonToggled)
        pin_button.toggled.connect(self.pinButtonToggled)
Пример #10
0
class QDockWindow(QDockFrame):
    """ A QDockFrame which holds a toplevel dock area.

    """
    #: The static resize margins for the dock window.
    ResizeMargins = QMargins(5, 5, 5, 5)

    #: The static normal contents margins for the dock window.
    NormalMargins = QMargins(5, 20, 5, 5)

    #: The static maximized margins for the dock window.
    MaximizedMargins = QMargins(0, 20, 0, 0)

    #: The minimum offset for the window buttons from the right edge.
    MinButtonOffset = 5

    class FrameState(QDockFrame.FrameState):
        """ A private class for managing window drag state.

        """
        #: The press position in the window title bar.
        press_pos = Typed(QPoint)

        #: Whether or not the window is being dragged by the user.
        dragging = Bool(False)

        #: Whether the window is inside it's close event.
        in_close_event = Bool(False)

    def __init__(self, manager, parent=None):
        """ Initialize a QDockWindow.

        Parameters
        ----------
        manager : DockManager
            The dock manager which owns the dock window.

        parent : QWidget or None
            The parent of the dock window, or None.

        """
        super(QDockWindow, self).__init__(manager, parent)
        self.setWindowFlags(Qt.Tool | Qt.FramelessWindowHint)
        self.setAttribute(Qt.WA_Hover, True)
        self.setMouseTracking(True)
        layout = QDockFrameLayout()
        layout.setSizeConstraint(QLayout.SetMinAndMaxSize)
        layout.setContentsMargins(self.NormalMargins)
        self.setLayout(layout)
        self.setDockArea(QDockArea())
        buttons = self._title_buttons = QDockWindowButtons(self)
        buttons.maximizeButtonClicked.connect(self.showMaximized)
        buttons.restoreButtonClicked.connect(self.showNormal)
        buttons.closeButtonClicked.connect(self.close)
        buttons.linkButtonToggled.connect(self.linkButtonToggled)

    #--------------------------------------------------------------------------
    # Reimplementations
    #--------------------------------------------------------------------------
    def showMaximized(self):
        """ Handle a show maximized request for the window.

        """
        self.layout().setContentsMargins(self.MaximizedMargins)
        super(QDockWindow, self).showMaximized()
        title_buttons = self._title_buttons
        buttons = title_buttons.buttons()
        buttons |= title_buttons.RestoreButton
        buttons &= ~title_buttons.MaximizeButton
        buttons &= ~title_buttons.LinkButton
        title_buttons.setButtons(buttons)
        title_buttons.setLinked(False)
        self._updateButtonGeometry()

    def showNormal(self):
        """ Handle a show normal request for the window.

        """
        super(QDockWindow, self).showNormal()
        self.applyNormalState()
        self._updateButtonGeometry()

    def applyNormalState(self):
        """ Apply the proper state for normal window geometry.

        """
        self.layout().setContentsMargins(self.NormalMargins)
        title_buttons = self._title_buttons
        buttons = title_buttons.buttons()
        buttons |= title_buttons.MaximizeButton
        buttons |= title_buttons.LinkButton
        buttons &= ~title_buttons.RestoreButton
        title_buttons.setButtons(buttons)
        title_buttons.setLinked(False)

    def titleBarGeometry(self):
        """ Get the geometry rect for the title bar.

        Returns
        -------
        result : QRect
            The geometry rect for the title bar, expressed in frame
            coordinates. An invalid rect is returned if title bar
            should not be active.

        """
        cmargins = self.layout().contentsMargins()
        if self.isMaximized():
            return QRect(0, 0, self.width(), cmargins.top())
        rmargins = self.ResizeMargins
        width = self.width() - (cmargins.left() + cmargins.right())
        height = cmargins.top() - rmargins.top()
        return QRect(cmargins.left(), rmargins.top(), width, height)

    def resizeMargins(self):
        """ Get the margins to use for resizing the container.

        Returns
        -------
        result : QMargins
            The margins to use for container resizing when the container
            is a top-level window.

        """
        if self.isMaximized():
            return QMargins()
        return self.ResizeMargins

    #--------------------------------------------------------------------------
    # Framework API
    #--------------------------------------------------------------------------
    def dockArea(self):
        """ Get the dock area installed on the container.

        Returns
        -------
        result : QDockArea or None
            The dock area installed in the container, or None.

        """
        return self.layout().getWidget()

    def setDockArea(self, dock_area):
        """ Set the dock area for the container.

        Parameters
        ----------
        dock_area : QDockArea
            The dock area to use in the container.

        """
        old = self.dockArea()
        if old is not None:
            old.removeEventFilter(self)
        self.layout().setWidget(dock_area)
        if dock_area is not None:
            dock_area.installEventFilter(self)

    def isLinked(self):
        """ Get whether or not the window is linked.

        """
        return self._title_buttons.isLinked()

    def setLinked(self, linked):
        """ Set whether or not the window is linked.

        This method should be reimplemented by a subclass.

        Parameters
        ----------
        linked : bool
            True if the window is considered linked, False otherwise.

        """
        self._title_buttons.setLinked(linked)

    def toggleMaximized(self):
        """ Toggle the maximized state of the window.

        """
        if self.isMaximized():
            self.showNormal()
        else:
            self.showMaximized()

    def eventFilter(self, area, event):
        """ Filter the events on the dock area.

        This filter listens for contents changes on the dock area and
        will close the window when the dock area is empty.

        """
        if event.type() == DockAreaContentsChanged and area.isEmpty():
            # Hide the window so that it doesn't steal events from
            # the floating window when this window is closed.
            self.hide()
            # Close the window later so that the event filter can
            # return before the child dock area is destroyed.
            QMetaObject.invokeMethod(self, 'close', Qt.QueuedConnection)
        return False

    #--------------------------------------------------------------------------
    # Event Handlers
    #--------------------------------------------------------------------------
    def closeEvent(self, event):
        """ Handle a close event for the window.

        """
        # Protect against reentrency and posted contents events which
        # get delivered after the manager has already been removed.
        state = self.frame_state
        if state.in_close_event:
            return
        manager = self.manager()
        if manager is None:
            return
        state.in_close_event = True
        manager.close_window(self, event)
        state.in_close_event = False

    def resizeEvent(self, event):
        """ Handle the resize event for the dock window.

        """
        super(QDockWindow, self).resizeEvent(event)
        self._updateButtonGeometry()

    def mouseDoubleClickEvent(self, event):
        """ Handle the mouse double click event for the dock window.

        This handler will toggle the maximization of the window if the
        click occurs within the title bar.

        """
        event.ignore()
        if event.button() == Qt.LeftButton:
            geo = self.titleBarGeometry()
            geo.setRight(self._title_buttons.geometry().left())
            if geo.contains(event.pos()):
                self.toggleMaximized()
                event.accept()

    def hoverMoveEvent(self, event):
        """ Handle the hover move event for the dock window.

        This reimplementation unsets the cursor when the mouse hovers
        over the dock window buttons.

        """
        if self._title_buttons.geometry().contains(event.pos()):
            self.unsetCursor()
        else:
            super(QDockWindow, self).hoverMoveEvent(event)

    def titleBarMousePressEvent(self, event):
        """ Handle the mouse press event for the dock window.

        Returns
        -------
        result : bool
            True if the event is handled, False otherwise.

        """
        if event.button() == Qt.LeftButton:
            state = self.frame_state
            if state.press_pos is None:
                state.press_pos = event.pos()
                return True
        return False

    def titleBarMouseMoveEvent(self, event):
        """ Handle the mouse move event for the dock window.

        Returns
        -------
        result : bool
            True if the event is handled, False otherwise.

        """
        state = self.frame_state
        if state.press_pos is not None:
            global_pos = event.globalPos()
            if self.isMaximized():
                coeff = state.press_pos.x() / float(self.width())
                self.showNormal()
                button_width = self._title_buttons.width()
                margins = self.layout().contentsMargins()
                max_x = self.width() - margins.right() - button_width - 5
                test_x = int(coeff * self.width())
                new_x = max(5, min(test_x, max_x))
                state.press_pos.setX(new_x)
                state.press_pos.setY(margins.top() / 2)
            target_pos = global_pos - state.press_pos
            self.manager().drag_move_frame(self, target_pos, global_pos)
            return True
        return False

    def titleBarMouseReleaseEvent(self, event):
        """ Handle the mouse release event for the dock window.

        Returns
        -------
        result : bool
            True if the event is handled, False otherwise.

        """
        if event.button() == Qt.LeftButton:
            state = self.frame_state
            if state.press_pos is not None:
                self.manager().drag_release_frame(self, event.globalPos())
                state.dragging = False
                state.press_pos = None
                return True
        return False

    #--------------------------------------------------------------------------
    # Private API
    #--------------------------------------------------------------------------
    def _updateButtonGeometry(self):
        """ Update the geometry of the window buttons.

        This method will set the geometry of the window buttons
        according to the current window size.

        """
        title_buttons = self._title_buttons
        size = title_buttons.minimumSizeHint()
        margins = self.layout().contentsMargins()
        offset = max(self.MinButtonOffset, margins.right())
        x = self.width() - size.width() - offset
        rect = QRect(x, 1, size.width(), size.height())
        title_buttons.setGeometry(rect)