Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qfocusframe.cpp
Go to the documentation of this file.
1
// Copyright (C) 2016 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
// Qt-Security score:significant reason:default
4
5
#
include
"qfocusframe.h"
6
#
include
"qstyle.h"
7
#
include
"qbitmap.h"
8
#
include
"qstylepainter.h"
9
#
include
"qstyleoption.h"
10
#
include
"qdebug.h"
11
#
include
<
private
/
qwidget_p
.
h
>
12
13
QT_BEGIN_NAMESPACE
14
15
class
QFocusFramePrivate
:
public
QWidgetPrivate
16
{
17
Q_DECLARE_PUBLIC(QFocusFrame)
18
QWidget
*
widget
;
19
QWidget *frameParent;
20
bool
showFrameAboveWidget;
21
public
:
22
QFocusFramePrivate
() {
23
widget =
nullptr
;
24
frameParent =
nullptr
;
25
sendChildEvents =
false
;
26
showFrameAboveWidget =
false
;
27
}
28
void
updateSize
();
29
void
update
();
30
};
31
32
void
QFocusFramePrivate
::
update
()
33
{
34
Q_Q(QFocusFrame);
35
q->setParent(frameParent);
36
updateSize
(
)
;
37
if
(q->parentWidget()->rect().intersects(q->geometry())) {
38
if
(showFrameAboveWidget)
39
q->raise();
40
else
41
q->stackUnder(widget);
42
q->show();
43
}
else
{
44
q->hide();
45
}
46
}
47
48
void
QFocusFramePrivate
::
updateSize
()
49
{
50
Q_Q(QFocusFrame);
51
if
(!widget)
52
return
;
53
54
QStyleOption opt;
55
q->initStyleOption(&opt);
56
int
vmargin = q->style()->pixelMetric(QStyle::PM_FocusFrameVMargin, &opt, q),
57
hmargin = q->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, &opt, q);
58
QPoint pos(widget->x(), widget->y());
59
if
(q->parentWidget() != widget->parentWidget())
60
pos = widget->parentWidget()->mapTo(q->parentWidget(), pos);
61
QRect geom(pos.x()-hmargin, pos.y()-vmargin,
62
widget->width()+(hmargin*2), widget->height()+(vmargin*2));
63
if
(q->geometry() == geom)
64
return
;
65
66
q->setGeometry(geom);
67
68
opt.rect = q->rect();
69
QStyleHintReturnMask
mask;
70
if
(q->style()->styleHint(QStyle::SH_FocusFrame_Mask, &opt, q, &mask))
71
q->setMask(mask.region);
72
}
73
74
/*!
75
Initialize \a option with the values from this QFocusFrame. This method is useful
76
for subclasses when they need a QStyleOption, but don't want to fill
77
in all the information themselves.
78
79
\sa QStyleOption::initFrom()
80
*/
81
void
QFocusFrame::initStyleOption(QStyleOption *option)
const
82
{
83
if
(!option)
84
return
;
85
86
option->initFrom(
this
);
87
}
88
89
/*!
90
\class QFocusFrame
91
\brief The QFocusFrame widget provides a focus frame which can be
92
outside of a widget's normal paintable area.
93
94
\ingroup basicwidgets
95
\inmodule QtWidgets
96
97
Normally an application will not need to create its own
98
QFocusFrame as QStyle will handle this detail for
99
you. A style writer can optionally use a QFocusFrame to have a
100
focus area outside of the widget's paintable geometry. In this way
101
space need not be reserved for the widget to have focus but only
102
set on a QWidget with QFocusFrame::setWidget. It is, however,
103
legal to create your own QFocusFrame on a custom widget and set
104
its geometry manually via QWidget::setGeometry however you will
105
not get auto-placement when the focused widget changes size or
106
placement.
107
*/
108
109
/*!
110
Constructs a QFocusFrame.
111
112
The focus frame will not monitor \a parent for updates but rather
113
can be placed manually or by using QFocusFrame::setWidget. A
114
QFocusFrame sets Qt::WA_NoChildEventsForParent attribute; as a
115
result the parent will not receive a QEvent::ChildAdded event,
116
this will make it possible to manually set the geometry of the
117
QFocusFrame inside of a QSplitter or other child event monitoring
118
widget.
119
120
\sa QFocusFrame::setWidget()
121
*/
122
123
QFocusFrame::QFocusFrame(QWidget *parent)
124
: QWidget(*
new
QFocusFramePrivate, parent, { })
125
{
126
setAttribute(Qt::WA_TransparentForMouseEvents);
127
setFocusPolicy(Qt::NoFocus);
128
setAttribute(Qt::WA_NoChildEventsForParent,
true
);
129
setAttribute(Qt::WA_AcceptDrops, style()->styleHint(QStyle::SH_FocusFrame_AboveWidget,
nullptr
,
this
));
130
}
131
132
/*!
133
Destructor.
134
*/
135
136
QFocusFrame::~QFocusFrame()
137
{
138
}
139
140
/*!
141
QFocusFrame will track changes to \a widget and resize itself automatically.
142
If the monitored widget's parent changes, QFocusFrame will follow the widget
143
and place itself around the widget automatically. If the monitored widget is deleted,
144
QFocusFrame will set it to zero.
145
146
\sa QFocusFrame::widget()
147
*/
148
149
void
150
QFocusFrame::setWidget(QWidget *widget)
151
{
152
Q_D(QFocusFrame);
153
154
if
(style()->styleHint(QStyle::SH_FocusFrame_AboveWidget,
nullptr
,
this
))
155
d->showFrameAboveWidget =
true
;
156
else
157
d->showFrameAboveWidget =
false
;
158
159
if
(widget == d->widget)
160
return
;
161
if
(d->widget) {
162
// Remove event filters from the widget hierarchy.
163
QWidget *p = d->widget;
164
do
{
165
p->removeEventFilter(
this
);
166
if
(!d->showFrameAboveWidget || p == d->frameParent)
167
break
;
168
p = p->parentWidget();
169
}
while
(p);
170
}
171
if
(widget && !widget->isWindow() && widget->parentWidget()->windowType() != Qt::SubWindow) {
172
d->widget = widget;
173
d->widget->installEventFilter(
this
);
174
QWidget *p = widget->parentWidget();
175
QWidget *prev =
nullptr
;
176
if
(d->showFrameAboveWidget) {
177
// Find the right parent for the focus frame.
178
while
(p) {
179
// Traverse the hirerarchy of the 'widget' for setting event filter.
180
// During this if come across toolbar or a top level, use that
181
// as the parent for the focus frame. If we find a scroll area
182
// use its viewport as the parent.
183
bool
isScrollArea =
false
;
184
if
(p->isWindow() || p->inherits(
"QToolBar"
) || (isScrollArea = p->inherits(
"QAbstractScrollArea"
))) {
185
d->frameParent = p;
186
// The previous one in the hierarchy will be the viewport.
187
if
(prev && isScrollArea)
188
d->frameParent = prev;
189
break
;
190
}
else
{
191
p->installEventFilter(
this
);
192
prev = p;
193
p = p->parentWidget();
194
}
195
}
196
}
else
{
197
d->frameParent = p;
198
}
199
d->update();
200
}
else
{
201
d->widget =
nullptr
;
202
hide();
203
}
204
}
205
206
/*!
207
Returns the currently monitored widget for automatically resize and
208
update.
209
210
\sa QFocusFrame::setWidget()
211
*/
212
213
QWidget *
214
QFocusFrame::widget()
const
215
{
216
Q_D(
const
QFocusFrame);
217
return
d->widget;
218
}
219
220
221
/*! \reimp */
222
void
223
QFocusFrame::paintEvent(QPaintEvent *)
224
{
225
Q_D(QFocusFrame);
226
227
if
(!d->widget)
228
return
;
229
230
QStylePainter p(
this
);
231
QStyleOption option;
232
initStyleOption(&option);
233
const
int
vmargin = style()->pixelMetric(QStyle::PM_FocusFrameVMargin, &option,
this
);
234
const
int
hmargin = style()->pixelMetric(QStyle::PM_FocusFrameHMargin, &option,
this
);
235
QWidgetPrivate *wd = qt_widget_private(d->widget);
236
QRect rect = wd->clipRect().adjusted(0, 0, hmargin*2, vmargin*2);
237
p.setClipRect(rect);
238
p.drawControl(QStyle::CE_FocusFrame, option);
239
}
240
241
242
/*! \reimp */
243
bool
244
QFocusFrame::eventFilter(QObject *o, QEvent *e)
245
{
246
Q_D(QFocusFrame);
247
if
(o == d->widget) {
248
switch
(e->type()) {
249
case
QEvent::Move:
250
case
QEvent::Resize:
251
d->updateSize();
252
break
;
253
case
QEvent::Hide:
254
case
QEvent::StyleChange:
255
hide();
256
break
;
257
case
QEvent::ParentChange:
258
if
(d->showFrameAboveWidget) {
259
QWidget *w = d->widget;
260
setWidget(
nullptr
);
261
setWidget(w);
262
}
else
{
263
d->update();
264
}
265
break
;
266
case
QEvent::Show:
267
d->update();
268
show();
269
break
;
270
case
QEvent::PaletteChange:
271
setPalette(d->widget->palette());
272
break
;
273
case
QEvent::ZOrderChange:
274
if
(style()->styleHint(QStyle::SH_FocusFrame_AboveWidget,
nullptr
,
this
))
275
raise();
276
else
277
stackUnder(d->widget);
278
break
;
279
case
QEvent::Destroy:
280
setWidget(
nullptr
);
281
break
;
282
default
:
283
break
;
284
}
285
}
else
if
(d->showFrameAboveWidget) {
286
// Handle changes in the parent widgets we are monitoring.
287
switch
(e->type()) {
288
case
QEvent::Move:
289
case
QEvent::Resize:
290
d->updateSize();
291
break
;
292
case
QEvent::ZOrderChange:
293
raise();
294
break
;
295
default
:
296
break
;
297
}
298
}
299
return
false
;
300
}
301
302
/*! \reimp */
303
bool
QFocusFrame::event(QEvent *e)
304
{
305
Q_D(QFocusFrame);
306
307
switch
(e->type()) {
308
case
QEvent::Move:
309
case
QEvent::Resize:
310
if
(d->widget) {
311
// When we're tracking a widget, we don't allow anyone to move the focus frame around.
312
// We do our best with event filters to make it stay on top of the widget, so trying to
313
// move the frame somewhere else will be flaky at best. This can e.g happen for general
314
// purpose code, like QAbstractScrollView, that bulk-moves all children a certain distance.
315
// So we need to call updateSize() when that happens to ensure that the focus frame stays
316
// on top of the widget.
317
d->updateSize();
318
}
319
break
;
320
default
:
321
return
QWidget::event(e);
322
}
323
return
true
;
324
}
325
326
QT_END_NAMESPACE
327
328
#
include
"moc_qfocusframe.cpp"
QFocusFramePrivate
Definition
qfocusframe.cpp:16
QFocusFramePrivate::update
void update()
Definition
qfocusframe.cpp:32
QFocusFramePrivate::updateSize
void updateSize()
Definition
qfocusframe.cpp:48
QFocusFramePrivate::QFocusFramePrivate
QFocusFramePrivate()
Definition
qfocusframe.cpp:22
QStyleHintReturnMask
The QStyleHintReturnMask class provides style hints that return a QRegion.
Definition
qstyleoption.h:730
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
qtbase
src
widgets
widgets
qfocusframe.cpp
Generated on
for Qt by
1.18.0