--- a/eric7/E5Gui/E5PassivePopup.py Sat May 22 17:01:51 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,254 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2010 - 2021 Detlev Offenbach <detlev@die-offenbachs.de> -# - -""" -Module implementing dialog-like popup that displays messages without -interrupting the user. -""" - -import enum - -from PyQt6.QtCore import pyqtSignal, Qt, QTimer, QPoint, QRect -from PyQt6.QtWidgets import QFrame, QVBoxLayout, QApplication - - -class E5PassivePopupStyle(enum.Enum): - """ - Class defining the popup styles. - """ - BOXED = 0 # box with no shadow - STYLED = 1 # styled panel with no shadow - CUSTOM = 128 # reserved for extensions - - -class E5PassivePopup(QFrame): - """ - Class implementing dialog-like popup that displays messages without - interrupting the user. - - @signal clicked emitted to indicate a mouse button click - """ - DefaultPopupTime = 6 * 1000 # time im milliseconds - - clicked = pyqtSignal((), (QPoint, )) - - def __init__(self, style=E5PassivePopupStyle.BOXED, parent=None): - """ - Constructor - - @param style style of the popup - @type E5PassivePopupStyle - @param parent reference to the parent widget - @type QWidget - """ - super().__init__(None) - - self.__msgView = None - self.__topLayout = None - self.__hideDelay = E5PassivePopup.DefaultPopupTime - self.__hideTimer = QTimer(self) - self.__autoDelete = False - self.__fixedPosition = QPoint() - - self.setWindowFlags( - Qt.WindowType.Tool | - Qt.WindowType.X11BypassWindowManagerHint | - Qt.WindowType.WindowStaysOnTopHint | - Qt.WindowType.FramelessWindowHint - ) - if style == E5PassivePopupStyle.STYLED: - self.setFrameStyle(QFrame.Shape.StyledPanel | QFrame.Shadow.Plain) - else: - # default style is Boxed - Plain - self.setFrameStyle(QFrame.Shape.Box | QFrame.Shadow.Plain) - self.setLineWidth(2) - self.__hideTimer.timeout.connect(self.hide) - self.clicked.connect(self.hide) - - self.__customData = {} # dictionary to store some custom data - - def setView(self, child): - """ - Public method to set the message view. - - @param child reference to the widget to set as the message view - (QWidget) - """ - self.__msgView = child - self.__topLayout = QVBoxLayout(self) - self.__topLayout.addWidget(self.__msgView) - self.__topLayout.activate() - - def view(self): - """ - Public method to get a reference to the message view. - - @return reference to the message view (QWidget) - """ - return self.__msgView - - def setVisible(self, visible): - """ - Public method to show or hide the popup. - - @param visible flag indicating the visibility status (boolean) - """ - if not visible: - super().setVisible(visible) - return - - if self.size() != self.sizeHint(): - self.resize(self.sizeHint()) - - if self.__fixedPosition.isNull(): - self.__positionSelf() - else: - self.move(self.__fixedPosition) - super().setVisible(True) - - delay = self.__hideDelay - if delay < 0: - delay = E5PassivePopup.DefaultPopupTime - if delay > 0: - self.__hideTimer.start(delay) - - def show(self, p=None): - """ - Public slot to show the popup. - - @param p position for the popup (QPoint) - """ - if p is not None: - self.__fixedPosition = p - super().show() - - def setTimeout(self, delay): - """ - Public method to set the delay for the popup is removed automatically. - - Setting the delay to 0 disables the timeout. If you're doing this, you - may want to connect the clicked() signal to the hide() slot. Setting - the delay to -1 makes it use the default value. - - @param delay value for the delay in milliseconds (integer) - """ - self.__hideDelay = delay - if self.__hideTimer.isActive(): - if delay: - if delay == -1: - delay = E5PassivePopup.DefaultPopupTime - self.__hideTimer.start(delay) - else: - self.__hideTimer.stop() - - def timeout(self): - """ - Public method to get the delay before the popup is removed - automatically. - - @return the delay before the popup is removed automatically (integer) - """ - return self.__hideDelay - - def mouseReleaseEvent(self, evt): - """ - Protected method to handle a mouse release event. - - @param evt reference to the mouse event (QMouseEvent) - """ - self.clicked.emit() - self.clicked.emit(evt.position().toPoint()) - - def hideEvent(self, evt): - """ - Protected method to handle the hide event. - - @param evt reference to the hide event (QHideEvent) - """ - self.__hideTimer.stop() - - def __defaultArea(self): - """ - Private method to determine the default rectangle to be passed to - moveNear(). - - @return default rectangle (QRect) - """ - return QRect(100, 100, 200, 200) - - def __positionSelf(self): - """ - Private method to position the popup. - """ - self.__moveNear(self.__defaultArea()) - - def __moveNear(self, target): - """ - Private method to move the popup to be adjacent to the specified - rectangle. - - @param target rectangle to be placed at (QRect) - """ - pos = self.__calculateNearbyPoint(target) - self.move(pos.x(), pos.y()) - - def __calculateNearbyPoint(self, target): - """ - Private method to calculate the position to place the popup near the - specified rectangle. - - @param target rectangle to be placed at (QRect) - @return position to place the popup (QPoint) - """ - pos = target.topLeft() - x = pos.x() - y = pos.y() - w = self.minimumSizeHint().width() - h = self.minimumSizeHint().height() - - r = QApplication.screenAt(QPoint(x + w // 2, y + h // 2)).geometry() - - if x < r.center().x(): - x += target.width() - else: - x -= w - - # It's apparently trying to go off screen, so display it ALL at the - # bottom. - if (y + h) > r.bottom(): - y = r.bottom() - h - - if (x + w) > r.right(): - x = r.right() - w - - if y < r.top(): - y = r.top() - - if x < r.left(): - x = r.left() - - return QPoint(x, y) - - def setCustomData(self, key, data): - """ - Public method to set some custom data. - - @param key key for the custom data - @type str - @param data data to be stored - @type any - """ - self.__customData[key] = data - - def getCustomData(self, key): - """ - Public method to get some custom data. - - @param key key for the custom data - @type str - @return stored data - @rtype any - """ - return self.__customData[key]