QGIS API Documentation  3.20.0-Odense (decaadbb31)
qgsfloatingwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsfloatingwidget.cpp
3  ---------------------
4  begin : April 2016
5  copyright : (C) 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 "qgsfloatingwidget.h"
17 #include <QEvent>
18 #include <QStyleOption>
19 #include <QPainter>
20 
21 //
22 // QgsFloatingWidget
23 //
24 
26  : QWidget( parent )
27 {
28  if ( parent )
29  {
30  mParentEventFilter = new QgsFloatingWidgetEventFilter( parent );
31  parent->installEventFilter( mParentEventFilter );
32  connect( mParentEventFilter, &QgsFloatingWidgetEventFilter::anchorPointChanged, this, &QgsFloatingWidget::onAnchorPointChanged );
33  }
34 }
35 
36 void QgsFloatingWidget::setAnchorWidget( QWidget *widget )
37 {
38  if ( widget == mAnchorWidget )
39  return;
40 
41  // remove existing event filter
42  if ( mAnchorWidget )
43  {
44  mAnchorWidget->removeEventFilter( mAnchorEventFilter );
45  delete mAnchorEventFilter;
46  mAnchorEventFilter = nullptr;
47  }
48 
49  mAnchorWidget = widget;
50  if ( mAnchorWidget )
51  {
52  mAnchorEventFilter = new QgsFloatingWidgetEventFilter( mAnchorWidget );
53  mAnchorWidget->installEventFilter( mAnchorEventFilter );
54  connect( mAnchorEventFilter, &QgsFloatingWidgetEventFilter::anchorPointChanged, this, &QgsFloatingWidget::onAnchorPointChanged );
55  }
56 
57  onAnchorPointChanged();
58  emit anchorWidgetChanged( mAnchorWidget );
59 }
60 
62 {
63  return mAnchorWidget;
64 }
65 
67 {
68  if ( point == mFloatAnchorPoint )
69  return;
70 
71  mFloatAnchorPoint = point;
72  onAnchorPointChanged();
73  emit anchorPointChanged( mFloatAnchorPoint );
74 }
75 
77 {
78  if ( point == mAnchorWidgetAnchorPoint )
79  return;
80 
81  mAnchorWidgetAnchorPoint = point;
82  onAnchorPointChanged();
83  emit anchorWidgetPointChanged( mAnchorWidgetAnchorPoint );
84 }
85 
86 void QgsFloatingWidget::showEvent( QShowEvent *e )
87 {
88  QWidget::showEvent( e );
89  onAnchorPointChanged();
90 }
91 
92 void QgsFloatingWidget::paintEvent( QPaintEvent *e )
93 {
94  Q_UNUSED( e )
95  QStyleOption opt;
96  opt.init( this );
97  QPainter p( this );
98  style()->drawPrimitive( QStyle::PE_Widget, &opt, &p, this );
99 }
100 
101 void QgsFloatingWidget::resizeEvent( QResizeEvent *e )
102 {
103  QWidget::resizeEvent( e );
104  onAnchorPointChanged();
105 }
106 
107 void QgsFloatingWidget::onAnchorPointChanged()
108 {
109  if ( !parentWidget() )
110  return;
111 
112  if ( mAnchorWidget )
113  {
114  QPoint anchorWidgetOrigin;
115 
116  switch ( mAnchorWidgetAnchorPoint )
117  {
118  case TopLeft:
119  anchorWidgetOrigin = QPoint( 0, 0 );
120  break;
121  case TopMiddle:
122  anchorWidgetOrigin = QPoint( mAnchorWidget->width() / 2, 0 );
123  break;
124  case TopRight:
125  anchorWidgetOrigin = QPoint( mAnchorWidget->width(), 0 );
126  break;
127  case MiddleLeft:
128  anchorWidgetOrigin = QPoint( 0, mAnchorWidget->height() / 2 );
129  break;
130  case Middle:
131  anchorWidgetOrigin = QPoint( mAnchorWidget->width() / 2, mAnchorWidget->height() / 2 );
132  break;
133  case MiddleRight:
134  anchorWidgetOrigin = QPoint( mAnchorWidget->width(), mAnchorWidget->height() / 2 );
135  break;
136  case BottomLeft:
137  anchorWidgetOrigin = QPoint( 0, mAnchorWidget->height() );
138  break;
139  case BottomMiddle:
140  anchorWidgetOrigin = QPoint( mAnchorWidget->width() / 2, mAnchorWidget->height() );
141  break;
142  case BottomRight:
143  anchorWidgetOrigin = QPoint( mAnchorWidget->width(), mAnchorWidget->height() );
144  break;
145  }
146 
147  anchorWidgetOrigin = mAnchorWidget->mapTo( parentWidget(), anchorWidgetOrigin );
148  int anchorX = anchorWidgetOrigin.x();
149  int anchorY = anchorWidgetOrigin.y();
150 
151  switch ( mFloatAnchorPoint )
152  {
153  case TopLeft:
154  break;
155  case TopMiddle:
156  anchorX = anchorX - width() / 2;
157  break;
158  case TopRight:
159  anchorX = anchorX - width();
160  break;
161  case MiddleLeft:
162  anchorY = anchorY - height() / 2;
163  break;
164  case Middle:
165  anchorY = anchorY - height() / 2;
166  anchorX = anchorX - width() / 2;
167  break;
168  case MiddleRight:
169  anchorX = anchorX - width();
170  anchorY = anchorY - height() / 2;
171  break;
172  case BottomLeft:
173  anchorY = anchorY - height();
174  break;
175  case BottomMiddle:
176  anchorX = anchorX - width() / 2;
177  anchorY = anchorY - height();
178  break;
179  case BottomRight:
180  anchorX = anchorX - width();
181  anchorY = anchorY - height();
182  break;
183  }
184 
185  // constrain x so that widget floats within parent widget
186  anchorX = std::clamp( anchorX, 0, parentWidget()->width() - width() );
187 
188  move( anchorX, anchorY );
189  }
190 }
191 
192 //
193 // QgsFloatingWidgetEventFilter
194 //
195 
197 QgsFloatingWidgetEventFilter::QgsFloatingWidgetEventFilter( QWidget *parent )
198  : QObject( parent )
199 {
200 
201 }
202 
203 bool QgsFloatingWidgetEventFilter::eventFilter( QObject *object, QEvent *event )
204 {
205  Q_UNUSED( object )
206  switch ( event->type() )
207  {
208  case QEvent::Move:
209  case QEvent::Resize:
210  emit anchorPointChanged();
211  return false;
212  default:
213  return false;
214  }
215 }
216 
void anchorWidgetPointChanged(QgsFloatingWidget::AnchorPoint point)
Emitted when the anchor widget point changes.
void setAnchorWidget(QWidget *widget)
Sets the widget to "anchor" the floating widget to.
QgsFloatingWidget(QWidget *parent=nullptr)
Constructor for QgsFloatingWidget.
void setAnchorWidgetPoint(AnchorPoint point)
Returns the anchor widget's anchor point, which corresponds to the point on the anchor widget which t...
void resizeEvent(QResizeEvent *e) override
void anchorPointChanged(QgsFloatingWidget::AnchorPoint point)
Emitted when the anchor point changes.
AnchorPoint
Reference points for anchoring widget position.
@ BottomMiddle
Bottom center of widget.
@ TopMiddle
Top center of widget.
@ MiddleRight
Middle right of widget.
@ MiddleLeft
Middle left of widget.
@ BottomRight
Bottom-right of widget.
@ BottomLeft
Bottom-left of widget.
@ Middle
Middle of widget.
@ TopLeft
Top-left of widget.
@ TopRight
Top-right of widget.
void paintEvent(QPaintEvent *e) override
void setAnchorPoint(AnchorPoint point)
Sets the floating widget's anchor point, which corresponds to the point on the widget which should re...
void anchorWidgetChanged(QWidget *widget)
Emitted when the anchor widget changes.
void showEvent(QShowEvent *e) override