def removeContainer(self, container): """ Remove a container from its dock bar. Parameters ---------- container : QDockContainer The container to remove from the dock bars. """ button = self._widgets.pop(container, None) if button is not None: container.setParent(None) container.setPinned(False, quiet=True) container.frame_state.in_dock_bar = False container.alerted.disconnect(button.onAlerted) item = self._widgets.pop(button) item.setParent(None) self._untrackForResize(item) dock_bar = self._getDockBar(button.position()) button.toggled.disconnect(self._onButtonToggled) button.setParent(None) if dock_bar.isEmpty(): self._dock_bars[dock_bar.position()] = None dock_bar.setParent(None) event = QEvent(DockAreaContentsChanged) QApplication.sendEvent(self.parent(), event)
def setCloseButtonVisible(self, index, visible): """ Set the close button visibility for the given tab index. Parameters ---------- index : int The index of the tab to set the close button visibility. visible : bool Whether or not the close button should be visible. """ if index < 0 or index >= self.count(): return button = self.tabButton(index, QTabBar.RightSide) if button is not None: if button.isVisibleTo(self) != visible: # The public QTabBar api does not provide a way to # trigger the 'layoutTabs' method of QTabBarPrivate # and there are certain operations (such as modifying # a tab close button) which need to have that happen. # A workaround is to send a dummy resize event. button.setVisible(visible) if not visible: button.resize(0, 0) else: button.resize(button.sizeHint()) size = self.size() event = QResizeEvent(size, size) QApplication.sendEvent(self, event) self.update()
def mousePressEvent(self, event): """ Handle the mouse press event for the tab bar. This handler will set the internal '_has_mouse' flag if the left mouse button is pressed on a tab. """ super(QDockTabBar, self).mousePressEvent(event) self._has_mouse = False if event.button() == Qt.LeftButton: if self.tabAt(event.pos()) != -1: self._has_mouse = True elif event.button() == Qt.RightButton: index = self.tabAt(event.pos()) if index != -1: button = self.tabButton(index, QTabBar.RightSide) if button.geometry().contains(event.pos()): return item = self.parent().widget(index).dockItem() item.titleBarRightClicked.emit(event.globalPos()) # Emitting the clicked signal may have caused a popup # menu to open, which will have grabbed the mouse. When # this happens, the hover leave event is not sent and # the tab bar will be stuck in the hovered paint state. # Manual checking as 'underMouse' yields False negatives. p = self.mapFromGlobal(QCursor.pos()) if not self.rect().contains(p): QApplication.sendEvent(self, QEvent(QEvent.HoverLeave))
def mouseMoveEvent(self, event): """ Handle the mouse move event for the tab bar. This handler will undock the tab if the mouse is held and the drag leaves the boundary of the container by the application drag distance amount. """ super(QDockTabBar, self).mouseMoveEvent(event) if not self._has_mouse: return pos = event.pos() if self.rect().contains(pos): return x = max(0, min(pos.x(), self.width())) y = max(0, min(pos.y(), self.height())) dist = (QPoint(x, y) - pos).manhattanLength() if dist > QApplication.startDragDistance(): # Fake a mouse release event so that the tab resets its # internal state and finalizes the animation for the tab. # The button must be Qt.LeftButton, not event.button(). btn = Qt.LeftButton mod = event.modifiers() evt = QMouseEvent(QEvent.MouseButtonRelease, pos, btn, btn, mod) QApplication.sendEvent(self, evt) container = self.parent().widget(self.currentIndex()) container.untab(event.globalPos()) self._has_mouse = False
def unplug_container(area, container): """ Unplug a container from a dock area. Parameters ---------- area : QDockArea The dock area in which the container lives. container : QDockContainer The container to remove from the dock area. Returns ------- result : bool True on success, False otherwise. """ root = area.centralWidget() if root is None: return False if root is container: root.hide() root.setParent(None) area.setCentralWidget(None) QApplication.sendEvent(area, QEvent(DockAreaContentsChanged)) return True success, replace = _unplug(root, container) if not success: return False if replace is not None: area.setCentralWidget(replace) QApplication.sendEvent(area, QEvent(DockAreaContentsChanged)) return True
def plug_frame(area, widget, frame, guide): """ Plug a dock frame into a dock area. Parameters ---------- area : QDockArea The dock area which owns the layout into which the container is being plugged. widget : QWidget The widget under the mouse. This should be one of QDockSplitterHandle, QDockTabWidget, or QDockContainer. frame : QDockContainer or QDockWindow The dock container or window to be plugged into the area. This should already be unplugged from any other layout. guide : QGuideRose.Guide The guide rose guide which indicates how to perform the plugging. Returns ------- result : bool True if the plugging was successful, False otherwise. """ if not isinstance(frame, (QDockContainer, QDockWindow)): return False res = _PLUG_HANDLERS[guide](area, widget, frame, guide) if res: QApplication.sendEvent(area, QEvent(DockAreaContentsChanged)) return res
def plug_frame(area, widget, frame, guide): """ Plug a dock frame into a dock area. Parameters ---------- area : QDockArea The dock area which owns the layout into which the container is being plugged. widget : QWidget The widget under the mouse. This should be one of QDockSplitterHandle, QDockTabWidget, or QDockContainer. frame : QDockContainer or QDockWindow The dock container or window to be plugged into the area. guide : QGuideRose.Guide The guide rose guide which indicates how to perform the plugging. Returns ------- result : bool True if the plugging was successful, False otherwise. """ if not isinstance(frame, (QDockContainer, QDockWindow)): return False res = _PLUG_HANDLERS[guide](area, widget, frame, guide) if res: QApplication.sendEvent(area, QEvent(DockAreaContentsChanged)) return res
def unplug_container(area, container): """ Unplug a container from a dock area. Parameters ---------- area : QDockArea The dock area in which the container lives. container : QDockContainer The container to remove from the dock area. Returns ------- result : bool True on success, False otherwise. """ root = area.layoutWidget() if root is None: return False if root is container: root.hide() root.setParent(None) area.setLayoutWidget(None) QApplication.sendEvent(area, QEvent(DockAreaContentsChanged)) return True success, replace = _unplug(root, container) if not success: return False if replace is not None: area.setLayoutWidget(replace) QApplication.sendEvent(area, QEvent(DockAreaContentsChanged)) return True
def mousePressEvent(self, event): """ Handle the mouse press event for the tab bar. This handler will set the internal '_has_mouse' flag if the left mouse button is pressed on a tab. """ super(QDockTabBar, self).mousePressEvent(event) self._has_mouse = False if event.button() == Qt.LeftButton: index = self.tabAt(event.pos()) if index != -1: self._has_mouse = True data = self._tab_data[index] container = data.container if container is not None: # likey a no-op, but just in case container.dockItem().clearAlert() elif event.button() == Qt.RightButton: index = self.tabAt(event.pos()) if index != -1: button = self.tabButton(index, QTabBar.RightSide) if button.geometry().contains(event.pos()): return item = self.parent().widget(index).dockItem() item.titleBarRightClicked.emit(event.globalPos()) # Emitting the clicked signal may have caused a popup # menu to open, which will have grabbed the mouse. When # this happens, the hover leave event is not sent and # the tab bar will be stuck in the hovered paint state. # Manual checking as 'underMouse' yields False negatives. p = self.mapFromGlobal(QCursor.pos()) if not self.rect().contains(p): QApplication.sendEvent(self, QEvent(QEvent.HoverLeave))
def addContainer(self, container, position, index=-1): """ Add a container to the specified dock bar. Parameters ---------- container : QDockContainer The container to add to the dock bar. It should already be unplugged from a layout or other dock manager before being added to this manager. position : QDockBar.Position The position of the dock bar to which the container should be added. index : int, optional The index at which to insert the item. The default is -1 and will append the item to the dock bar. """ assert isinstance(position, QDockBar.Position) self.removeContainer(container) container.setPinned(True, quiet=True) container.frame_state.in_dock_bar = True button = QDockBarButton() button.setText(container.title()) button.setIcon(container.icon()) button.toggled.connect(self._onButtonToggled) button.pressed.connect(self._onButtonPressed) container.alerted.connect(button.onAlerted) dock_bar = self._getDockBar(position) dock_bar.insertButton(index, button) item = QDockBarItem(self.parent().centralPane(), position=position) item.hide() item.setWidget(container) container.show() self._widgets[button] = item self._widgets[container] = button event = QEvent(DockAreaContentsChanged) QApplication.sendEvent(self.parent(), event)