E5Gui/E5PassivePopup.py

changeset 634
7b84cbd2f752
child 791
9ec2ac20e54e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/E5Gui/E5PassivePopup.py	Sun Sep 19 14:00:57 2010 +0200
@@ -0,0 +1,207 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2010 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing dialog-like popup that displays messages without 
+interrupting the user.
+"""
+
+from PyQt4.QtCore import pyqtSignal, Qt, QTimer, QPoint, QRect
+from PyQt4.QtGui import QFrame, QVBoxLayout, QApplication
+
+class E5PassivePopup(QFrame):
+    """
+    Class implementing dialog-like popup that displays messages without 
+    interrupting the user.
+    """
+    Boxed = 0
+    Custom = 128
+    
+    clicked = pyqtSignal((), (QPoint, ))
+    
+    def __init__(self, parent = None):
+        """
+        Constructor
+        
+        @param parent reference to the parent widget (QWidget)
+        """
+        QFrame.__init__(self, None)
+        
+        self.__popupStyle = DEFAULT_POPUP_TYPE
+        self.__msgView = None
+        self.__topLayout = None
+        self.__hideDelay = DEFAULT_POPUP_TIME
+        self.__hideTimer = QTimer(self)
+        self.__autoDelete = False
+        self.__fixedPosition = QPoint()
+        
+        self.setWindowFlags(POPUP_FLAGS)
+        self.setFrameStyle(QFrame.Box | QFrame.Plain)
+        self.setLineWidth(2)
+        self.__hideTimer.timeout.connect(self.hide)
+        self.clicked[()].connect(self.hide)
+    
+    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:
+            QFrame.setVisible(self, visible)
+            return
+        
+        if self.size() != self.sizeHint():
+            self.resize(self.sizeHint())
+        
+        if self.__fixedPosition.isNull():
+            self.__positionSelf()
+        else:
+            self.move(self.__fixedPosition)
+        QFrame.setVisible(self, True)
+        
+        delay = self.__hideDelay
+        if delay < 0:
+            delay = DEFAULT_POPUP_TIME
+        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
+        QFrame.show(self)
+    
+    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 = DEFAULT_POPUP_TIME
+                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[(QPoint, )].emit(evt.pos())
+    
+    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.desktop().screenGeometry(QPoint(x + w // 2, y + h // 2))
+        
+        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)
+
+DEFAULT_POPUP_TYPE = E5PassivePopup.Boxed
+DEFAULT_POPUP_TIME = 6 * 1000
+POPUP_FLAGS = Qt.WindowFlags(Qt.Tool | Qt.X11BypassWindowManagerHint | \
+    Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint)

eric ide

mercurial