QGIS API Documentation  3.8.0-Zanzibar (11aff65)
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 #include <QScrollBar>
20 
21 // milliseconds to swallow child wheel events for after a scroll occurs
22 #define TIMEOUT 1000
23 
24 QgsScrollArea::QgsScrollArea( QWidget *parent )
25  : QScrollArea( parent )
26  , mFilter( new ScrollAreaFilter( this, viewport() ) )
27 {
28  viewport()->installEventFilter( mFilter );
29 }
30 
31 void QgsScrollArea::wheelEvent( QWheelEvent *e )
32 {
33  //scroll occurred, reset timer
35  QScrollArea::wheelEvent( e );
36 }
37 
38 void QgsScrollArea::resizeEvent( QResizeEvent *event )
39 {
40  if ( mVerticalOnly && widget() )
41  widget()->setFixedWidth( event->size().width() );
42  QScrollArea::resizeEvent( event );
43 }
44 
46 {
47  mTimer.setSingleShot( true );
48  mTimer.start( TIMEOUT );
49 }
50 
52 {
53  return mTimer.isActive();
54 }
55 
56 void QgsScrollArea::setVerticalOnly( bool verticalOnly )
57 {
58  mVerticalOnly = verticalOnly;
59  if ( mVerticalOnly )
60  setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
61 
62  if ( mVerticalOnly && widget() )
63  widget()->setFixedWidth( size().width() );
64 }
65 
67 
68 ScrollAreaFilter::ScrollAreaFilter( QgsScrollArea *parent, QWidget *viewPort )
69  : QObject( parent )
70  , mScrollAreaWidget( parent )
71  , mViewPort( viewPort )
72 {}
73 
74 bool ScrollAreaFilter::eventFilter( QObject *obj, QEvent *event )
75 {
76  switch ( event->type() )
77  {
78  case QEvent::ChildAdded:
79  {
80  // need to install filter on all child widgets as well
81  QChildEvent *ce = static_cast<QChildEvent *>( event );
82  addChild( ce->child() );
83  break;
84  }
85 
86  case QEvent::ChildRemoved:
87  {
88  QChildEvent *ce = static_cast<QChildEvent *>( event );
89  removeChild( ce->child() );
90  break;
91  }
92 
93  case QEvent::Wheel:
94  {
95  if ( obj == mViewPort )
96  {
97  // scrolling scroll area - kick off the timer to block wheel events in children
98  mScrollAreaWidget->scrollOccurred();
99  }
100  else
101  {
102  if ( mScrollAreaWidget->hasScrolled() )
103  {
104  // swallow wheel events for children shortly after scroll occurs
105  return true;
106  }
107  }
108  break;
109  }
110 
111  default:
112  break;
113  }
114  return QObject::eventFilter( obj, event );
115 }
116 
117 void ScrollAreaFilter::addChild( QObject *child )
118 {
119  if ( child && child->isWidgetType() )
120  {
121  child->installEventFilter( this );
122 
123  // also install filter on existing children
124  const auto constChildren = child->children();
125  for ( QObject *c : constChildren )
126  {
127  addChild( c );
128  }
129  }
130 }
131 
132 void ScrollAreaFilter::removeChild( QObject *child )
133 {
134  if ( child && child->isWidgetType() )
135  {
136  child->removeEventFilter( this );
137 
138  // also remove filter on existing children
139  const auto constChildren = child->children();
140  for ( QObject *c : constChildren )
141  {
142  removeChild( c );
143  }
144  }
145 }
146 
void setVerticalOnly(bool verticalOnly)
Sets whether the scroll area only applies vertical.
bool hasScrolled() const
Returns true if a scroll recently occurred within the QScrollArea or its child viewport() ...
void resizeEvent(QResizeEvent *event) override
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()...