
    eb                         d dl Z d dlZd dlmZmZ ddlmZ ddlmZ ddlmZ ddl	m
Z
mZmZmZ dd	lmZmZmZ d
 ZdgZ G d dej(                        Zy)    N)perf_counterperf_counter_ns   )debug)getConfigOption)Point)QtCoreQtGui	QtWidgetsisQObjectAlive   )
HoverEventMouseClickEventMouseDragEventc                      t               dz  S )Ni@B )r        G/usr/lib/python3/dist-packages/pyqtgraph/GraphicsScene/GraphicsScene.py<lambda>r      s    O%0 r   GraphicsScenec                   4    e Zd ZdZ ej
                  e      Z ej
                  e      Z ej
                  e      Z	 ej
                         Z
 ej
                  e      Z ej
                  e      Z ej                         ZdZddefdZd Zd ZdefdZd	 Z fd
Zd Z fdZd Z fdZ fdZddZddZd Zd Z d Z!ejD                  jF                  jH                  ejD                  jJ                  jL                  dfdZ'd Z(d Z)d Z*d Z+ xZ,S )r   a<  
    Extension of QGraphicsScene that implements a complete, parallel mouse event system.
    (It would have been preferred to just alter the way QGraphicsScene creates and delivers 
    events, but this turned out to be impossible because the constructor for QGraphicsMouseEvent
    is private)
    
      *  Generates MouseClicked events in addition to the usual press/move/release events.
         (This works around a problem where it is impossible to have one item respond to a
         drag if another is watching for a click.)
      *  Adjustable radius around click that will catch objects so you don't have to click *exactly* over small/thin objects
      *  Global context menu--if an item implements a context menu, then its parent(s) may also add items to the menu.
      *  Allows items to decide _before_ a mouse click which item will be the recipient of mouse events.
         This lets us indicate unambiguously to the user which item they are about to click/drag on
      *  Eats mouseMove events that occur too soon after a mouse press.
      *  Reimplements items() and itemAt() to circumvent PyQt bug

    ====================== ====================================================================
    **Signals**
    sigMouseClicked(event) Emitted when the mouse is clicked over the scene. Use ev.pos() to
                           get the click position relative to the item that was clicked on,
                           or ev.scenePos() to get the click position in scene coordinates.
                           See :class:`pyqtgraph.GraphicsScene.mouseEvents.MouseClickEvent`.                        
    sigMouseMoved(pos)     Emitted when the mouse cursor moves over the scene. The position
                           is given in scene coordinates.
    sigMouseHover(items)   Emitted when the mouse is moved over the scene. Items is a list
                           of items under the cursor.
    sigItemAdded(item)     Emitted when an item is added via addItem(). The item is given.
    sigItemRemoved(item)   Emitted when an item is removed via removeItem(). The item is given.
    ====================== ====================================================================
    
    Mouse interaction is as follows:
    
    1) Every time the mouse moves, the scene delivers both the standard hoverEnter/Move/LeaveEvents 
       as well as custom HoverEvents. 
    2) Items are sent HoverEvents in Z-order and each item may optionally call event.acceptClicks(button), 
       acceptDrags(button) or both. If this method call returns True, this informs the item that _if_ 
       the user clicks/drags the specified mouse button, the item is guaranteed to be the 
       recipient of click/drag events (the item may wish to change its appearance to indicate this).
       If the call to acceptClicks/Drags returns False, then the item is guaranteed to *not* receive
       the requested event (because another item has already accepted it). 
    3) If the mouse is clicked, a mousePressEvent is generated as usual. If any items accept this press event, then
       No click/drag events will be generated and mouse interaction proceeds as defined by Qt. This allows
       items to function properly if they are expecting the usual press/move/release sequence of events.
       (It is recommended that items do NOT accept press events, and instead use click/drag events)
       Note: The default implementation of QGraphicsItem.mousePressEvent will *accept* the event if the 
       item is has its Selectable or Movable flags enabled. You may need to override this behavior.
    4) If no item accepts the mousePressEvent, then the scene will begin delivering mouseDrag and/or mouseClick events.
       If the mouse is moved a sufficient distance (or moved slowly enough) before the button is released, 
       then a mouseDragEvent is generated.
       If no drag events are generated before the button is released, then a mouseClickEvent is generated. 
    5) Click/drag events are delivered to the item that called acceptClicks/acceptDrags on the HoverEvent
       in step 1. If no such items exist, then the scene attempts to deliver the events to items near the event. 
       ClickEvents may be delivered in this way even if no
       item originally claimed it could accept the click. DragEvents may only be delivered this way if it is the initial
       move in a drag.
    NclickRadiusc                    t         j                  j                  | |       | j                  |       | j	                  |       d | _        g | _        g | _        d | _        d | _	        d | _
        t        j                         | _        d | _        d| _        t!        j"                  t$        j&                  j)                  dd      |       g| _        | j*                  d   j,                  j/                  | j0                         d | _        d| _        y )Ng      ?r   z	Export...r   )r   QGraphicsScene__init__setClickRadiussetMoveDistanceexportDirectoryclickEventsdragButtonsmouseGrabberdragItemlastDragweakrefWeakKeyDictionary
hoverItemslastHoverEventminDragTimer
   QActionr	   QCoreApplication	translatecontextMenu	triggeredconnectshowExportDialogexportDialog_lastMoveEventTime)selfr   moveDistanceparents       r   r   zGraphicsScene.__init__W   s      ))$7K(\*# !335"!MM&*A*A*K*KO]h*ikopq%%--d.C.CD "#r   c                 b    | j                          t        j                  j                  | g| S N)prepareForPaintr   r   render)r2   argss     r   r8   zGraphicsScene.renderl   s*    ''..t;d;;r   c                 8    | j                   j                          y)zCalled before every render. This method will inform items that the scene is about to
        be rendered by emitting sigPrepareForPaint.
        
        This allows items to delay expensive processing until they know a paint will be required.N)sigPrepareForPaintemitr2   s    r   r7   zGraphicsScene.prepareForPaintp   s    
 	$$&r   rc                 $    t        |      | _        y)a=  
        Set the distance away from mouse clicks to search for interacting items.
        When clicking, the scene searches first for items that directly intersect the click position
        followed by any other items that are within a rectangle that extends r pixels away from the 
        click position. 
        N)int_clickRadius)r2   r>   s     r   r   zGraphicsScene.setClickRadiusx   s      Fr   c                     || _         y)z
        Set the distance the mouse must move after a press before mouseMoveEvents will be delivered.
        This ensures that clicks with a small amount of movement are recognized as clicks instead of
        drags.
        N)_moveDistance)r2   ds     r   r   zGraphicsScene.setMoveDistance   s     r   c                 h   t         |   |       | j                         | j                  <|j	                         | j                  j	                         k7  r| j                  |       | j                  j                  t        |             | j                  |j	                               }|D ]  }|j                         s|j                         s%|j                         |j                  j                  z  sM|j                  t         j"                  j$                  j&                          y  y y r6   )supermousePressEventmouseGrabberItemr'   scenePossendHoverEventsr   appendr   items	isEnabled	isVisibleflagsGraphicsItemFlagItemIsFocusablesetFocusr	   QtFocusReasonMouseFocusReason)r2   evrL   i	__class__s       r   rG   zGraphicsScene.mousePressEvent   s    #  "*"". ;;=D$7$7$@$@$BB((,##OB$78 JJr{{}-E ;;=Q[[]	ADVDVDfDf8fJJvyy44EEF +r   c                 f    t        d      }|dk  ryd|z  }t               | j                  z
  |k\  ryy)NmouseRateLimitr   Tg     @@F)r   	getMillisr1   )r2   	rateLimitdelays      r   _moveEventIsAllowedz!GraphicsScene._moveEventIsAllowed   s@     $$45	> ";000E9r   c                    | j                         rBt               | _        | j                  j	                  |j                                t        |   |       | j                  |       |j                         rt        |   |       | j                         t               }d}t        j                  j                  j                  t        j                  j                  j                   t        j                  j                  j"                  fD ]  }|j                         |z  s|| j$                  vs&| j&                  D cg c]  }|j)                         |k(  s| }}|sV|d   }t+        |j                         |j                         z
        j-                         }|dk(  s/|| j.                  k  r!||j1                         z
  | j2                  k  r|xs t5        | j$                        dk(  }| j$                  j7                  |        t5        | j$                        dkD  r%| j9                  ||      r|j;                          y y y y y t        |   |       |j;                          y c c}w )NFr   )init)r^   r[   r1   sigMouseMovedr<   rI   rF   mouseMoveEventrJ   buttonsrH   r   r	   rS   MouseButton
LeftButtonMiddleButtonRightButtonr    r   buttonr   lengthrC   timer(   lenrK   sendDragEventaccept)	r2   rV   nowr`   btnecevdistrX   s	           r   rb   zGraphicsScene.mouseMoveEvent   s   ##%&/kD###BKKM2 G"2&  $zz|&r*((*2&.C D &		 5 5 @ @&))BWBWBdBdflfofof{f{  gH  gH   I = "

s 2$d&6&66.2.>.>"T!((*PSBS1"TC"T"&)!f',R[[]S\\^-K'L'S'S'U#'198J8J1JsUXU]U]U_O_bfbrbrOr$,'+'KD4D4D0E0J $ 0 0 7 7 <= 4++,q0--bt-<IIK = 1# 3 2 G"2&IIK! #Us   I5 I5c                 \    t        | j                        dk(  r| j                  |d       y y )Nr   T)exitOnly)rk   r    rJ   )r2   rV   s     r   
leaveEventzGraphicsScene.leaveEvent   s-    t A%  d 3 &r   c                    | j                         |j                         | j                  v rM| j                  |d      r|j	                          | j                  j                  |j                                n| j                  D cg c]&  }|j                         |j                         k(  s%|( }}|rC| j                  |d         r|j	                          	 | j                  j                  |d          |j                         sd | _        g | _        g | _        d | _        t        | A  |       | j#                  |       y c c}w # t        $ r t        j                  dt        d       Y yw xY w)NT)finalr   zA ValueError can occur here with errant QApplication.processEvent() calls, see https://github.com/pyqtgraph/pyqtgraph/pull/2580 for more information.r   )
stacklevel)rH   rh   r    rl   rm   remover   sendClickEvent
ValueErrorwarningswarnRuntimeWarningrc   r"   r#   rF   mouseReleaseEventrJ   )r2   rV   rp   rq   rX   s       r   r   zGraphicsScene.mouseReleaseEvent   s7     "*yy{d...%%b%5IIK  ''		4"&"2"2PQahhjBIIK6OqPP**3q62		
((//A7 zz| DM!D!D DM!"%R - Q &  4 +'(s   	&E0EE %E54E5c                     t         |   |       | j                         '| j                  j	                  t        |d             y y )NT)double)rF   mouseDoubleClickEventrH   r   rK   r   )r2   rV   rX   s     r   r   z#GraphicsScene.mouseDoubleClickEvent   s?    %b)  "*##OBt$DE +r   Fc                    |rd}g }t        d |      }nK|j                          }t        ||      }| j                  |d      }| j                  j	                  |       t        | j                  j                               }|D ]e  }t        |d      s||_	        || j                  vrd | j                  |<   d|_
        n|j                  |       d|_
        	 |j                  |       g d|_
        d|_        |D ]E  }||_	        	 t!        |      r#|j#                         | u r|j                  |       | j                  |= G |j%                         |j&                  j(                  k(  s7|j%                         |j&                  j*                  k(  r|j                         s|| _        y y y #  t        j                  d       Y BxY w#  t        j                  d       Y xY w# | j                  |= w xY w)NFT)	hoverable
hoverEventzError sending hover event:Error sending hover exit event:)r   rc   itemsNearEventsigMouseHoverr<   listr&   keyshasattrcurrentItementerry   r   r   printExcexitr   scenetypeTypeGraphicsSceneMousePressGraphicsSceneMouseMover'   )r2   rV   rt   
acceptablerL   event	prevItemsitems           r   rJ   zGraphicsScene.sendHoverEvents   s    JEtZ0EZZ\)Jr:.E'''>E##E*--/0	 	ADt\*$(!t.,0DOOD)"&EK$$T*"'EKAOOE*	A 
 
	*D $E* "$'DJJLD,@OOE* OOD)
	*  GGI888WWY"''888"'D BN8/ANN#?@B@AOOD)s$   F,.G	,G	G" G%%G4c                 |   t        || j                  d   | j                  ||      }|ro| j                  b| j                  9| j                  j                         j                  |j                         d       }nd }|H|j                         | u r6|| _        | j                  |_	        	 | j                  j                  |       n
| j                  |      D ]  }|j                         r|j                         s$t!        |d      s1||_	        	 |j                  |       |j#                         s[|| _        |j%                         |j&                  j(                  z  r3|j+                  t,        j.                  j0                  j2                          n; n9| j                  -| j                  |_	        	 | j                  j                  |       || _        |j#                         S #  t        j                  d       Y 0xY w#  t        j                  d       Y xY w#  t        j                  d       Y hxY w)Nr   )startfinishzError sending drag event:mouseDragEventr   )r   r   r#   r"   r'   	dragItemsgetrh   r   r   r   r   r   r   rN   rM   r   
isAcceptedrO   rP   rQ   rR   r	   rS   rT   rU   )r2   rV   r`   rw   r   acceptedItemr   s          r   rl   zGraphicsScene.sendDragEvent/  s    r4#3#3A#6TZ_`DMM)"".#22<<>BB5<<>SWX#'L,>,>,@D,H ,$(MM!@MM007 !//6 "D>>+4>>3C t%56,0)H //6 !++-,0DM#zz|d.C.C.S.SS $fii.C.C.T.T U!"  ]]& $EB,,U3 !!=@NN#>?H!NN+FGB@As$   ,G* H8H" *HH"H;c                    | j                   Dt        | j                   d      r.| j                   |_        | j                   j                  |       n,| j                  9| j                  j                         j                  |j                         d       }nd }|||_        	 |j                  |       n| j                  |      D ]  }|j                         r|j                         s$t        |d      s1||_        	 |j                  |       |j                         s[|j                         |j                  j                   z  r3|j#                  t$        j&                  j(                  j*                          n | j,                  j/                  |       |j                         S #  t        j                  d       Y DxY w#  t        j                  d       Y xY w)NmouseClickEventzError sending click event:)r"   r   r   r   r'   
clickItemsr   rh   r   r   r   rN   rM   r   rO   rP   rQ   rR   r	   rS   rT   rU   sigMouseClickedr<   )r2   rV   r   r   s       r   rz   zGraphicsScene.sendClickEventa  sz   ==$@Q)R!]]BNMM))"- "".#22==?CCBIIKQUV#'!-A 004 !//3 "D>>+4>>3C t%67)-I 004 ==?#zz|d.C.C.S.SS $fii.C.C.T.T U!" 	!!"%}}%ANN#?@I!NN+GHs   "F( >G(GGc                 |    t         j                  j                  | |      }| j                  j	                  |       |S r6   )r   r   addItemsigItemAddedr<   r2   r   rets      r   r   zGraphicsScene.addItem  s3    &&..tT:t$
r   c                 |    t         j                  j                  | |      }| j                  j	                  |       |S r6   )r   r   
removeItemsigItemRemovedr<   r   s      r   r   zGraphicsScene.removeItem  s3    &&11$=  &
r   c           	      2   | j                         d   }|j                         }t        |d      r|j                         }n|j	                         }fd| j                  ||||      }|j                  d       | j                  }	g }
d}|	dkD  r|j                  t        j                  ddd|	z  d|	z              j                         }|j                         }|j                         }t        j                  |j                         |dz  z
  |j!                         |dz  z
  ||      }| j                  ||||      }
|
j                  d       |D ]  }||
v s|
j#                  |        ||
z   }g }|D ]  }|rt        |d      s|j%                         | ur%|j'                         }|8|.|j)                  |j+                  |      j                               s!|j-                  |j+                  |            s|j/                  |        |S )	z
        Return an iterator that iterates first through the items that directly intersect point (in Z order)
        followed by any other items that are within the scene's click radius.
        r   buttonDownScenePosc                 X    | y| j                          | j                               z   S Nr   )zValue
parentItem)r   	absZValues    r   r   z/GraphicsScene.itemsNearEvent.<locals>.absZValue  s(    |;;=9T__->#???r   T)keyreverseNr   r   )viewsviewportTransformr   r   rI   rL   sortrA   
mapToScener	   QRectboundingRectwidthheightQRectFxyry   r   shape
intersectsmapFromScenecontainsrK   )r2   r   selMode	sortOrderr   viewtrpointitems_at_pointr>   items_within_radiusrgnrectwhr   	all_itemsselected_itemsr   r   s                      @r   r   zGraphicsScene.itemsNearEvent  s    zz|A##%5./,,.ENN$E	@ E7IrB	48  q5??6<<1a!eQU#CDQQSD

AA--	AE 15779q1u3DaKC"&**S'9b"I$$D$A& 5..'..t45 #%88	  	,D|!<zz|4'JJLE} $$T%6%6s%;%H%H%JK 1 1% 89%%d+	,  r   c                 (    | j                         d   S r   )r   r=   s    r   getViewWidgetzGraphicsScene.getViewWidget  s    zz|Ar   c           	      R   g }|| urn|j                         }|| }t        |d      s%|j                  |      xs g }t        |t              r|j                  |       n|j                  |       || urn|j                         }g }|D ]x  }t        |t        j                        r|j                         }n5t        |t        j                        st        d| dt        |       d      ||vsh|j                  |       z |r|j                          |j!                  |       |S )a  
        Can be called by any item in the scene to expand its context menu to include parent context menus.
        Parents may implement getContextMenus to add new menus / actions to the existing menu.
        getContextMenus must accept 1 argument (the event that generated the original menu) and
        return a single QMenu or a list of QMenus.
        
        The final menu will look like:
        
            |    Original Item 1
            |    Original Item 2
            |    ...
            |    Original Item N
            |    ------------------
            |    Parent Item 1
            |    Parent Item 2
            |    ...
            |    Grandparent Item 1
            |    ...
            
        
        ==============  ==================================================
        **Arguments:**
        item            The item that initially created the context menu 
                        (This is probably the item making the call to this function)
        menu            The context menu being shown by the item
        event           The original event that triggered the menu to appear.
        ==============  ==================================================
        getContextMenuszCannot add object z (type=z) to QMenu.)r   r   r   
isinstancer   extendrK   actionsr   QMenu
menuActionr
   r)   	Exceptionr   addSeparator
addActions)	r2   r   menur   
menusToAddsubMenusexistingActions	actsToAdd	menuOrActs	            r   addParentContextMenusz#GraphicsScene.addParentContextMenus  s#   < 
$??$D|4!23++E28bH(D)!!(+!!(+ $ ,,.	# 	,I)Y__5%002		5==9(74	?:K;W  /  +	, 	"r   c                 <    |j                   | _        | j                  S r6   )r   contextMenuItemr,   )r2   r   s     r   r   zGraphicsScene.getContextMenus  s    $11r   c                     | j                   ddlm } |j                  |       | _         | j                   j                  | j                         y )Nr   )r0   )r0    ExportDialogshowr   )r2   r0   s     r   r/   zGraphicsScene.showExportDialog  s>    $& , 9 9$ ?Dt334r   )r      N)F)FF)-__name__
__module____qualname____doc__r	   Signalobjectr   ra   r   r;   r   r   r$   WeakValueDictionary_addressCacheExportDirectoryr@   r   r8   r7   r   r   rG   r^   rb   ru   r   r   rJ   rl   rz   r   r   rS   ItemSelectionModeIntersectsItemShape	SortOrderDescendingOrderr   r   r   r   r/   __classcell__)rX   s   @r   r   r      s)   7r "FMM&)M!FMM&)M#fmmF+O& 6==(L"V]]6*N/G//1MO$C $*<'# #$%N4!@F
3(j/"d"H 		++??))%%55DL;z 5r   )r|   r$   rj   r   r   r   r   r   r   rS   r	   r
   r   r   mouseEventsr   r   r   r[   __all__r   r   r   r   r   <module>r      sF      .    9 9 D D0	 
O5I,, O5r   