QGIS API Documentation  3.2.0-Bonn (bc43194)
qgsscrollarea.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsscrollarea.cpp
3  -----------------
4  begin : March 2017
5  copyright : (C) 2017 by Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include <QEvent>
17 #include <QMouseEvent>
18 #include "qgsscrollarea.h"
19 
20 // milliseconds to swallow child wheel events for after a scroll occurs
21 #define TIMEOUT 1000
22 
23 QgsScrollArea::QgsScrollArea( QWidget *parent )
24  : QScrollArea( parent )
25  , mFilter( new ScrollAreaFilter( this, viewport() ) )
26 {
27  viewport()->installEventFilter( mFilter );
28 }
29 
30 void QgsScrollArea::wheelEvent( QWheelEvent *e )
31 {
32  //scroll occurred, reset timer
34  QScrollArea::wheelEvent( e );
35 }
36 
38 {
39  mTimer.setSingleShot( true );
40  mTimer.start( TIMEOUT );
41 }
42 
44 {
45  return mTimer.isActive();
46 }
47 
49 
50 ScrollAreaFilter::ScrollAreaFilter( QgsScrollArea *parent, QWidget *viewPort )
51  : QObject( parent )
52  , mScrollAreaWidget( parent )
53  , mViewPort( viewPort )
54 {}
55 
56 bool ScrollAreaFilter::eventFilter( QObject *obj, QEvent *event )
57 {
58  switch ( event->type() )
59  {
60  case QEvent::ChildAdded:
61  {
62  // need to install filter on all child widgets as well
63  QChildEvent *ce = static_cast<QChildEvent *>( event );
64  addChild( ce->child() );
65  break;
66  }
67 
68  case QEvent::ChildRemoved:
69  {
70  QChildEvent *ce = static_cast<QChildEvent *>( event );
71  removeChild( ce->child() );
72  break;
73  }
74 
75  case QEvent::Wheel:
76  {
77  if ( obj == mViewPort )
78  {
79  // scrolling scroll area - kick off the timer to block wheel events in children
80  mScrollAreaWidget->scrollOccurred();
81  }
82  else
83  {
84  if ( mScrollAreaWidget->hasScrolled() )
85  {
86  // swallow wheel events for children shortly after scroll occurs
87  return true;
88  }
89  }
90  break;
91  }
92 
93  default:
94  break;
95  }
96  return QObject::eventFilter( obj, event );
97 }
98 
99 void ScrollAreaFilter::addChild( QObject *child )
100 {
101  if ( child && child->isWidgetType() )
102  {
103  child->installEventFilter( this );
104 
105  // also install filter on existing children
106  Q_FOREACH ( QObject *c, child->children() )
107  {
108  addChild( c );
109  }
110  }
111 }
112 
113 void ScrollAreaFilter::removeChild( QObject *child )
114 {
115  if ( child && child->isWidgetType() )
116  {
117  child->removeEventFilter( this );
118 
119  // also remove filter on existing children
120  Q_FOREACH ( QObject *c, child->children() )
121  {
122  removeChild( c );
123  }
124  }
125 }
126 
bool hasScrolled() const
Returns true if a scroll recently occurred within the QScrollArea or its child viewport() ...
void wheelEvent(QWheelEvent *event) override
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QgsScrollArea(QWidget *parent=nullptr)
Constructor for QgsScrollArea.
#define TIMEOUT
A QScrollArea subclass with improved scrolling behavior.
Definition: qgsscrollarea.h:41
void scrollOccurred()
Should be called when a scroll occurs on with the QScrollArea itself or its child viewport()...