QGIS API Documentation  3.27.0-Master (597e8eebd4)
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 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
97  opt.init( this );
98 #else
99  opt.initFrom( this );
100 #endif
101  QPainter p( this );
102  style()->drawPrimitive( QStyle::PE_Widget, &opt, &p, this );
103 }
104 
105 void QgsFloatingWidget::resizeEvent( QResizeEvent *e )
106 {
107  QWidget::resizeEvent( e );
108  onAnchorPointChanged();
109 }
110 
111 void QgsFloatingWidget::onAnchorPointChanged()
112 {
113  if ( !parentWidget() )
114  return;
115 
116  if ( mAnchorWidget )
117  {
118  QPoint anchorWidgetOrigin;
119 
120  switch ( mAnchorWidgetAnchorPoint )
121  {
122  case TopLeft:
123  anchorWidgetOrigin = QPoint( 0, 0 );
124  break;
125  case TopMiddle:
126  anchorWidgetOrigin = QPoint( mAnchorWidget->width() / 2, 0 );
127  break;
128  case TopRight:
129  anchorWidgetOrigin = QPoint( mAnchorWidget->width(), 0 );
130  break;
131  case MiddleLeft:
132  anchorWidgetOrigin = QPoint( 0, mAnchorWidget->height() / 2 );
133  break;
134  case Middle:
135  anchorWidgetOrigin = QPoint( mAnchorWidget->width() / 2, mAnchorWidget->height() / 2 );
136  break;
137  case MiddleRight:
138  anchorWidgetOrigin = QPoint( mAnchorWidget->width(), mAnchorWidget->height() / 2 );
139  break;
140  case BottomLeft:
141  anchorWidgetOrigin = QPoint( 0, mAnchorWidget->height() );
142  break;
143  case BottomMiddle:
144  anchorWidgetOrigin = QPoint( mAnchorWidget->width() / 2, mAnchorWidget->height() );
145  break;
146  case BottomRight:
147  anchorWidgetOrigin = QPoint( mAnchorWidget->width(), mAnchorWidget->height() );
148  break;
149  }
150 
151  anchorWidgetOrigin = mAnchorWidget->mapTo( parentWidget(), anchorWidgetOrigin );
152  int anchorX = anchorWidgetOrigin.x();
153  int anchorY = anchorWidgetOrigin.y();
154 
155  switch ( mFloatAnchorPoint )
156  {
157  case TopLeft:
158  break;
159  case TopMiddle:
160  anchorX = anchorX - width() / 2;
161  break;
162  case TopRight:
163  anchorX = anchorX - width();
164  break;
165  case MiddleLeft:
166  anchorY = anchorY - height() / 2;
167  break;
168  case Middle:
169  anchorY = anchorY - height() / 2;
170  anchorX = anchorX - width() / 2;
171  break;
172  case MiddleRight:
173  anchorX = anchorX - width();
174  anchorY = anchorY - height() / 2;
175  break;
176  case BottomLeft:
177  anchorY = anchorY - height();
178  break;
179  case BottomMiddle:
180  anchorX = anchorX - width() / 2;
181  anchorY = anchorY - height();
182  break;
183  case BottomRight:
184  anchorX = anchorX - width();
185  anchorY = anchorY - height();
186  break;
187  }
188 
189  // constrain x so that widget floats within parent widget
190  anchorX = std::clamp( anchorX, 0, parentWidget()->width() - width() );
191 
192  move( anchorX, anchorY );
193  }
194 }
195 
196 //
197 // QgsFloatingWidgetEventFilter
198 //
199 
201 QgsFloatingWidgetEventFilter::QgsFloatingWidgetEventFilter( QWidget *parent )
202  : QObject( parent )
203 {
204 
205 }
206 
207 bool QgsFloatingWidgetEventFilter::eventFilter( QObject *object, QEvent *event )
208 {
209  Q_UNUSED( object )
210  switch ( event->type() )
211  {
212  case QEvent::Move:
213  case QEvent::Resize:
214  emit anchorPointChanged();
215  return false;
216  default:
217  return false;
218  }
219 }
220 
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