1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtWidgets module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qbitmap.h"
41#include "qevent.h"
42#include "qstylepainter.h"
43#include "qrubberband.h"
44#include "qtimer.h"
45
46#include "qstyle.h"
47#include "qstyleoption.h"
48
49#include <qdebug.h>
50
51#include <private/qwidget_p.h>
52
53QT_BEGIN_NAMESPACE
54
55//### a rubberband window type would be a more elegant solution
56#define RUBBERBAND_WINDOW_TYPE Qt::ToolTip
57
58class QRubberBandPrivate : public QWidgetPrivate
59{
60 Q_DECLARE_PUBLIC(QRubberBand)
61public:
62 QRect rect;
63 QRubberBand::Shape shape;
64 QRegion clipping;
65 void updateMask();
66};
67
68/*!
69 Initialize \a option with the values from this QRubberBand. This method
70 is useful for subclasses when they need a QStyleOptionRubberBand, but don't want
71 to fill in all the information themselves.
72
73 \sa QStyleOption::initFrom()
74*/
75void QRubberBand::initStyleOption(QStyleOptionRubberBand *option) const
76{
77 if (!option)
78 return;
79 option->initFrom(w: this);
80 option->shape = d_func()->shape;
81#ifndef Q_OS_MAC
82 option->opaque = true;
83#else
84 option->opaque = windowFlags() & RUBBERBAND_WINDOW_TYPE;
85#endif
86}
87
88/*!
89 \class QRubberBand
90 \brief The QRubberBand class provides a rectangle or line that can
91 indicate a selection or a boundary.
92
93 \inmodule QtWidgets
94
95 A rubber band is often used to show a new bounding area (as in a
96 QSplitter or a QDockWidget that is undocking). Historically this has
97 been implemented using a QPainter and XOR, but this approach
98 doesn't always work properly since rendering can happen in the
99 window below the rubber band, but before the rubber band has been
100 "erased".
101
102 You can create a QRubberBand whenever you need to render a rubber band
103 around a given area (or to represent a single line), then call
104 setGeometry(), move() or resize() to position and size it. A common
105 pattern is to do this in conjunction with mouse events. For example:
106
107 \snippet code/src_gui_widgets_qrubberband.cpp 0
108
109 If you pass a parent to QRubberBand's constructor, the rubber band will
110 display only inside its parent, but stays on top of other child widgets.
111 If no parent is passed, QRubberBand will act as a top-level widget.
112
113 Call show() to make the rubber band visible; also when the
114 rubber band is not a top-level. Hiding or destroying
115 the widget will make the rubber band disappear. The rubber band
116 can be a \l Rectangle or a \l Line (vertical or horizontal),
117 depending on the shape() it was given when constructed.
118*/
119
120// ### DOC: How about some nice convenience constructors?
121//QRubberBand::QRubberBand(QRubberBand::Type t, const QRect &rect, QWidget *p)
122//QRubberBand::QRubberBand(QRubberBand::Type t, int x, int y, int w, int h, QWidget *p)
123
124/*!
125 Constructs a rubber band of shape \a s, with parent \a p.
126
127 By default a rectangular rubber band (\a s is \c Rectangle) will
128 use a mask, so that a small border of the rectangle is all
129 that is visible. Some styles (e.g., native \macos) will
130 change this and call QWidget::setWindowOpacity() to make a
131 semi-transparent filled selection rectangle.
132*/
133QRubberBand::QRubberBand(Shape s, QWidget *p)
134 : QWidget(*new QRubberBandPrivate, p, (p && p->windowType() != Qt::Desktop) ? Qt::Widget : RUBBERBAND_WINDOW_TYPE)
135{
136 Q_D(QRubberBand);
137 d->shape = s;
138 setAttribute(Qt::WA_TransparentForMouseEvents);
139 setAttribute(Qt::WA_NoSystemBackground);
140 setAttribute(Qt::WA_WState_ExplicitShowHide);
141 setVisible(false);
142}
143
144/*!
145 Destructor.
146*/
147QRubberBand::~QRubberBand()
148{
149}
150
151/*!
152 \enum QRubberBand::Shape
153
154 This enum specifies what shape a QRubberBand should have. This is
155 a drawing hint that is passed down to the style system, and can be
156 interpreted by each QStyle.
157
158 \value Line A QRubberBand can represent a vertical or horizontal
159 line. Geometry is still given in rect() and the line
160 will fill the given geometry on most styles.
161
162 \value Rectangle A QRubberBand can represent a rectangle. Some
163 styles will interpret this as a filled (often
164 semi-transparent) rectangle, or a rectangular
165 outline.
166*/
167
168/*!
169 Returns the shape of this rubber band. The shape can only be set
170 upon construction.
171*/
172QRubberBand::Shape QRubberBand::shape() const
173{
174 Q_D(const QRubberBand);
175 return d->shape;
176}
177
178/*!
179 \internal
180*/
181void QRubberBandPrivate::updateMask()
182{
183 Q_Q(QRubberBand);
184 QStyleHintReturnMask mask;
185 QStyleOptionRubberBand opt;
186 q->initStyleOption(option: &opt);
187 if (q->style()->styleHint(stylehint: QStyle::SH_RubberBand_Mask, opt: &opt, widget: q, returnData: &mask)) {
188 q->setMask(mask.region);
189 } else {
190 q->clearMask();
191 }
192}
193
194/*!
195 \reimp
196*/
197void QRubberBand::paintEvent(QPaintEvent *)
198{
199 QStylePainter painter(this);
200 QStyleOptionRubberBand option;
201 initStyleOption(option: &option);
202 painter.drawControl(ce: QStyle::CE_RubberBand, opt: option);
203}
204
205/*!
206 \reimp
207*/
208void QRubberBand::changeEvent(QEvent *e)
209{
210 QWidget::changeEvent(e);
211 switch (e->type()) {
212 case QEvent::ParentChange:
213 if (parent()) {
214 setWindowFlags(windowFlags() & ~RUBBERBAND_WINDOW_TYPE);
215 } else {
216 setWindowFlags(windowFlags() | RUBBERBAND_WINDOW_TYPE);
217 }
218 break;
219 default:
220 break;
221 }
222
223 if (e->type() == QEvent::ZOrderChange)
224 raise();
225}
226
227/*!
228 \reimp
229*/
230void QRubberBand::showEvent(QShowEvent *e)
231{
232 raise();
233 e->ignore();
234}
235
236/*!
237 \reimp
238*/
239void QRubberBand::resizeEvent(QResizeEvent *)
240{
241 Q_D(QRubberBand);
242 d->updateMask();
243}
244
245/*!
246 \reimp
247*/
248void QRubberBand::moveEvent(QMoveEvent *)
249{
250 Q_D(QRubberBand);
251 d->updateMask();
252}
253
254/*!
255 \fn void QRubberBand::move(const QPoint &p);
256
257 \overload
258
259 Moves the rubberband to point \a p.
260
261 \sa resize()
262*/
263
264/*!
265 \fn void QRubberBand::move(int x, int y);
266
267 Moves the rubberband to point (\a x, \a y).
268
269 \sa resize()
270*/
271
272/*!
273 \fn void QRubberBand::resize(const QSize &size);
274
275 \overload
276
277 Resizes the rubberband so that its new size is \a size.
278
279 \sa move()
280*/
281
282/*!
283 \fn void QRubberBand::resize(int width, int height);
284
285 Resizes the rubberband so that its width is \a width, and its
286 height is \a height.
287
288 \sa move()
289*/
290
291/*!
292 \fn void QRubberBand::setGeometry(const QRect &rect)
293
294 Sets the geometry of the rubber band to \a rect, specified in the coordinate system
295 of its parent widget.
296
297 \sa QWidget::geometry
298*/
299void QRubberBand::setGeometry(const QRect &geom)
300{
301 QWidget::setGeometry(geom);
302}
303
304/*!
305 \fn void QRubberBand::setGeometry(int x, int y, int width, int height)
306 \overload
307
308 Sets the geometry of the rubberband to the rectangle whose top-left corner lies at
309 the point (\a x, \a y), and with dimensions specified by \a width and \a height.
310 The geometry is specified in the parent widget's coordinate system.
311*/
312
313/*! \reimp */
314bool QRubberBand::event(QEvent *e)
315{
316 return QWidget::event(event: e);
317}
318
319QT_END_NAMESPACE
320
321#include "moc_qrubberband.cpp"
322

source code of qtbase/src/widgets/widgets/qrubberband.cpp