Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
zoomwidget.cpp
Go to the documentation of this file.
1
// Copyright (C) 2016 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
// Qt-Security score:significant reason:default
4
5
#
include
"zoomwidget_p.h"
6
7
#
include
<
QtWidgets
/
qgraphicsscene
.
h
>
8
#
include
<
QtWidgets
/
qgraphicsproxywidget
.
h
>
9
#
include
<
QtWidgets
/
qmenu
.
h
>
10
#
include
<
QtWidgets
/
qscrollbar
.
h
>
11
12
#
include
<
QtGui
/
qaction
.
h
>
13
#
include
<
QtGui
/
qactiongroup
.
h
>
14
#
include
<
QtGui
/
qevent
.
h
>
15
16
#
include
<
QtCore
/
qtextstream
.
h
>
17
#
include
<
QtCore
/
qmath
.
h
>
18
#
include
<
QtCore
/
qdebug
.
h
>
19
#
include
<
QtCore
/
qlist
.
h
>
20
21
QT_BEGIN_NAMESPACE
22
23
using
namespace
Qt::StringLiterals;
24
25
enum
{
debugZoomWidget
= 0 };
26
27
static
const
int
menuZoomList
[] = { 100, 25, 50, 75, 125, 150 , 175, 200 };
28
29
namespace
qdesigner_internal
{
30
31
// ---------- ZoomMenu
32
33
ZoomMenu
::
ZoomMenu
(
QObject
*
parent
) :
34
QObject
(
parent
),
35
m_menuActions
(
new
QActionGroup
(
this
))
36
{
37
connect
(
m_menuActions
, &
QActionGroup
::
triggered
,
this
, &
ZoomMenu
::
slotZoomMenu
);
38
for
(
int
zoom
:
menuZoomList
) {
39
//: Zoom factor
40
QAction
*
a
=
m_menuActions
->
addAction
(
tr
(
"%1 %"
).
arg
(
zoom
));
41
a
->
setCheckable
(
true
);
42
a
->
setData
(
QVariant
(
zoom
));
43
if
(
zoom
== 100)
44
a
->
setChecked
(
true
);
45
m_menuActions
->
addAction
(
a
);
46
}
47
}
48
49
int
ZoomMenu
::
zoomOf
(
const
QAction
*
a
)
50
{
51
return
a
->
data
().
toInt
();
52
}
53
54
void
ZoomMenu
::
addActions
(
QMenu
*
m
)
55
{
56
const
auto
za
=
m_menuActions
->
actions
();
57
for
(
QAction
*
a
:
za
) {
58
m
->
addAction
(
a
);
59
if
(
zoomOf
(
a
) == 100)
60
m
->
addSeparator
();
61
}
62
}
63
64
int
ZoomMenu
::
zoom
()
const
65
{
66
return
m_menuActions
->
checkedAction
()->
data
().
toInt
();
67
}
68
69
void
ZoomMenu
::
setZoom
(
int
percent
)
70
{
71
const
auto
za
=
m_menuActions
->
actions
();
72
for
(
QAction
*
a
:
za
) {
73
if
(
zoomOf
(
a
) ==
percent
) {
74
a
->
setChecked
(
true
);
75
return
;
76
}
77
}
78
}
79
80
void
ZoomMenu
::
slotZoomMenu
(
QAction
*
a
)
81
{
82
emit
zoomChanged
(
zoomOf
(
a
));
83
}
84
85
QList
<
int
>
ZoomMenu
::
zoomValues
()
86
{
87
QList
<
int
>
rc
;
88
const
int
nz
=
sizeof
(
menuZoomList
)/
sizeof
(
int
);
89
rc
.
reserve
(
nz
);
90
for
(
int
i
= 0;
i
<
nz
;
i
++)
91
rc
.
push_back
(
menuZoomList
[
i
]);
92
return
rc
;
93
}
94
95
// --------- ZoomView
96
ZoomView
::
ZoomView
(
QWidget
*
parent
) :
97
QGraphicsView
(
parent
),
98
m_scene
(
new
QGraphicsScene
(
this
))
99
{
100
setHorizontalScrollBarPolicy
(
Qt
::
ScrollBarAlwaysOff
);
101
setVerticalScrollBarPolicy
(
Qt
::
ScrollBarAlwaysOff
);
102
setFrameShape
(
QFrame
::
NoFrame
);
103
setScene
(
m_scene
);
104
if
(
debugZoomWidget
)
105
qDebug
() <<
"scene"
<<
m_scene
->
sceneRect
();
106
107
}
108
109
int
ZoomView
::
zoom
()
const
110
{
111
return
m_zoom
;
112
}
113
114
void
ZoomView
::
scrollToOrigin
()
115
{
116
const
QPoint
origin
(0 ,0);
117
const
QPoint
current
=
scrollPosition
();
118
if
(
current
!=
origin
) {
119
if
(
debugZoomWidget
)
120
qDebug
() <<
"ZoomView::scrollToOrigin from "
<<
current
;
121
setScrollPosition
(
origin
);
122
}
123
}
124
125
void
ZoomView
::
setZoom
(
int
percent
)
126
{
127
if
(
debugZoomWidget
)
128
qDebug
() <<
"ZoomView::setZoom"
<<
percent
;
129
130
if
(
m_zoom
==
percent
)
131
return
;
132
133
m_zoom
=
percent
;
134
const
qreal
hundred
= 100.0;
135
m_zoomFactor
=
static_cast
<
qreal
>(
m_zoom
) /
hundred
;
136
137
applyZoom
();
138
if
(
m_zoomMenu
)
// Do not force them into existence
139
m_zoomMenu
->
setZoom
(
m_zoom
);
140
141
resetTransform
();
142
scale
(
m_zoomFactor
,
m_zoomFactor
);
143
}
144
145
void
ZoomView
::
applyZoom
()
146
{
147
}
148
149
qreal
ZoomView
::
zoomFactor
()
const
150
{
151
return
m_zoomFactor
;
152
}
153
154
bool
ZoomView
::
isZoomContextMenuEnabled
()
const
155
{
156
return
m_zoomContextMenuEnabled
;
157
}
158
159
void
ZoomView
::
setZoomContextMenuEnabled
(
bool
e
)
160
{
161
m_zoomContextMenuEnabled
=
e
;
162
}
163
164
ZoomMenu
*
ZoomView
::
zoomMenu
()
165
{
166
if
(!
m_zoomMenu
) {
167
m_zoomMenu
=
new
ZoomMenu
(
this
);
168
m_zoomMenu
->
setZoom
(
m_zoom
);
169
connect
(
m_zoomMenu
, &
ZoomMenu
::
zoomChanged
,
this
, &
ZoomView
::
setZoom
);
170
}
171
return
m_zoomMenu
;
172
}
173
174
void
ZoomView
::
contextMenuEvent
(
QContextMenuEvent
*
event
)
175
{
176
if
(
debugZoomWidget
> 1)
177
qDebug
() <<
"ZoomView::contextMenuEvent"
<<
event
->
pos
() <<
event
->
globalPos
() <<
zoom
() <<
'%'
;
178
179
if
(
m_zoomContextMenuEnabled
) {
180
showContextMenu
(
event
->
globalPos
());
181
}
else
{
182
QGraphicsView
::
contextMenuEvent
(
event
);
183
}
184
}
185
186
void
ZoomView
::
showContextMenu
(
const
QPoint
&
globalPos
)
187
{
188
QMenu
menu
;
189
zoomMenu
()->
addActions
(&
menu
);
190
menu
.
exec
(
globalPos
);
191
}
192
193
QPoint
ZoomView
::
scrollPosition
()
const
194
{
195
return
QPoint
(
horizontalScrollBar
()->
value
(),
verticalScrollBar
()->
value
());
196
}
197
198
void
ZoomView
::
setScrollPosition
(
const
QPoint
&
pos
)
199
{
200
horizontalScrollBar
()->
setValue
(
pos
.
x
());
201
verticalScrollBar
()->
setValue
(
pos
.
y
());
202
}
203
204
// -------------- ZoomProxyWidget
205
ZoomProxyWidget
::
ZoomProxyWidget
(
QGraphicsItem
*
parent
,
Qt
::
WindowFlags
wFlags
) :
206
QGraphicsProxyWidget
(
parent
,
wFlags
)
207
{
208
}
209
210
QVariant
ZoomProxyWidget
::
itemChange
(
GraphicsItemChange
change
,
const
QVariant
&
value
)
211
{
212
switch
(
change
) {
213
case
ItemPositionChange
: {
214
const
QPointF
newPos
=
value
.
toPointF
();
215
const
QPointF
desiredPos
=
QPointF
(0, 0);
216
if
(
newPos
!=
desiredPos
&&
debugZoomWidget
)
217
qDebug
() <<
"ZoomProxyWidget::itemChange: refusing "
<<
newPos
;
218
return
desiredPos
;
219
}
220
default
:
221
break
;
222
}
223
return
QGraphicsProxyWidget
::
itemChange
(
change
,
value
);
224
}
225
226
/* ZoomedEventFilterRedirector: Event filter for the zoomed widget.
227
* It redirects the events to another handler of ZoomWidget as its
228
* base class QScrollArea also implements eventFilter() for its viewport. */
229
230
static
constexpr
auto
zoomedEventFilterRedirectorNameC
=
"__qt_ZoomedEventFilterRedirector"_L1
;
231
232
class
ZoomedEventFilterRedirector
:
public
QObject
{
233
Q_DISABLE_COPY_MOVE
(
ZoomedEventFilterRedirector
)
234
235
public
:
236
explicit
ZoomedEventFilterRedirector
(
ZoomWidget
*
zw
,
QObject
*
parent
);
237
bool
eventFilter
(QObject *watched, QEvent *event)
override
;
238
239
private
:
240
ZoomWidget *m_zw;
241
};
242
243
ZoomedEventFilterRedirector
::ZoomedEventFilterRedirector(ZoomWidget *zw, QObject *parent) :
244
QObject(parent),
245
m_zw(zw)
246
{
247
setObjectName(zoomedEventFilterRedirectorNameC);
248
}
249
250
bool
ZoomedEventFilterRedirector
::
eventFilter
(QObject *watched, QEvent *event)
251
{
252
return
m_zw->zoomedEventFilter(watched, event);
253
}
254
255
256
// --------- ZoomWidget
257
258
ZoomWidget
::
ZoomWidget
(
QWidget
*
parent
) :
259
ZoomView
(
parent
)
260
{
261
setVerticalScrollBarPolicy
(
Qt
::
ScrollBarAlwaysOff
);
262
setHorizontalScrollBarPolicy
(
Qt
::
ScrollBarAlwaysOff
);
263
}
264
265
void
ZoomWidget
::
setWidget
(
QWidget
*
w
,
Qt
::
WindowFlags
wFlags
)
266
{
267
if
(
debugZoomWidget
)
268
qDebug
() <<
"ZoomWidget::setWidget"
<<
w
<<
Qt
::
bin
<<
wFlags
;
269
270
if
(
m_proxy
) {
271
scene
().
removeItem
(
m_proxy
);
272
if
(
QWidget
*
w
=
m_proxy
->
widget
()) {
273
// remove the event filter
274
if
(
QObject
*
evf
=
w
->
findChild
<
QObject
*>(
zoomedEventFilterRedirectorNameC
))
275
w
->
removeEventFilter
(
evf
);
276
}
277
m_proxy
->
deleteLater
();
278
}
279
// Set window flags on the outer proxy for them to take effect
280
m_proxy
=
createProxyWidget
(
nullptr
,
Qt
::
Window
);
281
m_proxy
->
setWidget
(
w
);
282
283
m_proxy
->
setWindowFlags
(
wFlags
);
284
scene
().
addItem
(
m_proxy
);
285
w
->
installEventFilter
(
new
ZoomedEventFilterRedirector
(
this
,
w
));
286
resizeToWidgetSize
();
// Do manually for new widget
287
m_proxy
->
show
();
288
}
289
290
bool
ZoomWidget
::
isWidgetZoomContextMenuEnabled
()
const
291
{
292
return
m_widgetZoomContextMenuEnabled
;
293
}
294
void
ZoomWidget
::
setWidgetZoomContextMenuEnabled
(
bool
e
)
295
{
296
m_widgetZoomContextMenuEnabled
=
e
;
297
}
298
299
QSize
ZoomWidget
::
viewPortMargin
()
const
300
{
301
return
QSize
(0, 0);
302
}
303
304
QSizeF
ZoomWidget
::
widgetDecorationSizeF
()
const
305
{
306
qreal
left
,
top
,
right
,
bottom
;
307
m_proxy
->
getWindowFrameMargins
(&
left
, &
top
, &
right
, &
bottom
);
308
const
QSizeF
rc
=
QSizeF
(
left
+
right
,
top
+
bottom
);
309
return
rc
;
310
}
311
312
QSize
ZoomWidget
::
widgetSize
()
const
313
{
314
if
(
m_proxy
)
315
return
m_proxy
->
widget
()->
size
();
316
return
QSize
(0, 0);
317
}
318
319
/* Convert widget size to QGraphicsView size.
320
* Watch out for limits (0, QWIDGETSIZE_MAX); just pass them on */
321
322
QSize
ZoomWidget
::
widgetSizeToViewSize
(
const
QSize
&
s
,
bool
*
ptrToValid
)
const
323
{
324
const
QSize
vpMargin
=
viewPortMargin
();
325
const
QSizeF
deco
=
widgetDecorationSizeF
();
326
const
int
width
=
s
.
width
();
327
328
QSize
rc
=
s
;
329
bool
valid
=
false
;
330
if
(
width
!= 0 &&
width
!=
QWIDGETSIZE_MAX
) {
331
valid
=
true
;
332
rc
.
setWidth
(
vpMargin
.
width
() +
qCeil
(
deco
.
width
() +
zoomFactor
() *
static_cast
<
qreal
>(
width
)));
333
}
334
335
const
int
height
=
s
.
height
();
336
if
(
height
!= 0 &&
height
!=
QWIDGETSIZE_MAX
) {
337
valid
=
true
;
338
rc
.
setHeight
(
vpMargin
.
height
() +
qCeil
(
deco
.
height
() +
zoomFactor
() *
static_cast
<
qreal
>(
height
)));
339
}
340
341
if
(
ptrToValid
)
342
*
ptrToValid
=
valid
;
343
344
return
rc
;
345
}
346
347
// On changing zoom: Make QGraphicsView big enough to hold the widget
348
void
ZoomWidget
::
resizeToWidgetSize
()
349
{
350
if
(!
m_proxy
)
351
return
;
352
353
m_viewResizeBlocked
=
true
;
354
// Convert size, apply transformed min/max size if applicable
355
const
QSize
wsize
=
widgetSize
();
356
const
QSize
viewSize
=
widgetSizeToViewSize
(
wsize
);
357
358
bool
hasMinimumSize
=
false
;
359
const
QSize
minimumSize
=
m_proxy
->
widget
()->
minimumSize
();
360
const
QSize
viewMinimumSize
=
widgetSizeToViewSize
(
minimumSize
, &
hasMinimumSize
);
361
362
bool
hasMaximumSize
=
false
;
363
const
QSize
maximumSize
=
m_proxy
->
widget
()->
maximumSize
();
364
const
QSize
viewMaximumSize
=
widgetSizeToViewSize
(
maximumSize
, &
hasMaximumSize
);
365
366
if
(
debugZoomWidget
) {
367
qDebug
()
368
<<
"ZoomWidget::resizeToWidgetSize()\n"
369
<<
"Widget: "
<<
wsize
<<
"(scaled)"
<< (
wsize
*
zoomFactor
()) <<
" Min/Max"
<<
minimumSize
<<
maximumSize
<<
'\n'
370
<<
" View: "
<<
viewSize
<<
hasMinimumSize
<<
viewMinimumSize
<<
hasMaximumSize
<<
viewMaximumSize
;
371
}
372
// Apply
373
if
(
hasMinimumSize
)
374
setMinimumSize
(
viewMinimumSize
);
375
if
(
hasMaximumSize
)
376
setMaximumSize
(
viewMaximumSize
);
377
// now resize
378
doResize
(
viewSize
);
379
if
(
debugZoomWidget
)
380
qDebug
() <<
"ZoomWidget::resizeToWidgetSize(): resulting view size"
<<
size
();
381
m_viewResizeBlocked
=
false
;
382
}
383
384
void
ZoomWidget
::
applyZoom
()
385
{
386
resizeToWidgetSize
();
387
}
388
389
/* virtual */
void
ZoomWidget
::
doResize
(
const
QSize
&
s
)
390
{
391
if
(
debugZoomWidget
> 1)
392
qDebug
() <<
">ZoomWidget::doResize() "
<<
s
;
393
resize
(
s
);
394
}
395
396
void
ZoomWidget
::
resizeEvent
(
QResizeEvent
*
event
)
397
{
398
/* QGraphicsView Resized from outside: Adapt widget. For some reason,
399
* the size passed in the event is not to be trusted. This might be due
400
* to some QScrollArea event fiddling. Have QScrollArea resize first
401
* and the use the size ZoomView::resizeEvent(event); */
402
if
(
m_proxy
&& !
m_viewResizeBlocked
) {
403
if
(
debugZoomWidget
> 1)
404
qDebug
() <<
'>'
<<
Q_FUNC_INFO
<<
size
() <<
")::resizeEvent from "
<<
event
->
oldSize
() <<
" to "
<<
event
->
size
();
405
const
QSizeF
newViewPortSize
=
size
() -
viewPortMargin
();
406
const
QSizeF
widgetSizeF
=
newViewPortSize
/
zoomFactor
() -
widgetDecorationSizeF
();
407
m_widgetResizeBlocked
=
true
;
408
m_proxy
->
widget
()->
resize
(
widgetSizeF
.
toSize
());
409
setSceneRect
(
QRectF
(
QPointF
(0, 0),
widgetSizeF
));
410
scrollToOrigin
();
411
m_widgetResizeBlocked
=
false
;
412
if
(
debugZoomWidget
> 1)
413
qDebug
() <<
'<'
<<
Q_FUNC_INFO
<<
widgetSizeF
<<
m_proxy
->
widget
()->
size
() <<
m_proxy
->
size
();
414
}
415
}
416
417
QSize
ZoomWidget
::
minimumSizeHint
()
const
418
{
419
if
(!
m_proxy
)
420
return
QGraphicsView
::
minimumSizeHint
();
421
422
const
QSizeF
wmsh
=
m_proxy
->
widget
()->
minimumSizeHint
();
423
const
QSize
rc
=
viewPortMargin
() + (
wmsh
*
zoomFactor
()).
toSize
();
424
if
(
debugZoomWidget
> 1)
425
qDebug
() <<
"minimumSizeHint()"
<<
rc
;
426
return
rc
;
427
}
428
429
QSize
ZoomWidget
::
sizeHint
()
const
430
{
431
if
(!
m_proxy
)
432
return
QGraphicsView
::
sizeHint
();
433
434
const
QSizeF
wsh
=
m_proxy
->
widget
()->
sizeHint
();
435
const
QSize
rc
=
viewPortMargin
() + (
wsh
*
zoomFactor
()).
toSize
();
436
if
(
debugZoomWidget
> 1)
437
qDebug
() <<
"sizeHint()"
<<
rc
;
438
return
rc
;
439
}
440
441
bool
ZoomWidget
::
zoomedEventFilter
(
QObject
*
/*watched*/
,
QEvent
*
event
)
442
{
443
switch
(
event
->
type
()) {
444
case
QEvent
::
KeyPress
:
445
if
(
debugZoomWidget
) {
// Debug helper: Press 'D' on the zoomed widget
446
const
QKeyEvent
*
kevent
=
static_cast
<
QKeyEvent
*>(
event
);
447
if
(
kevent
->
key
() ==
Qt
::
Key_D
)
448
dump
();
449
}
450
break
;
451
case
QEvent
::
Resize
:
452
if
(
debugZoomWidget
> 1) {
453
const
QResizeEvent
*
re
=
static_cast
<
const
QResizeEvent
*>(
event
);
454
qDebug
() <<
"ZoomWidget::zoomedEventFilter"
<<
re
->
oldSize
() <<
re
->
size
() <<
" at "
<<
m_proxy
->
widget
()->
geometry
();
455
}
456
if
(!
m_widgetResizeBlocked
)
457
resizeToWidgetSize
();
458
459
break
;
460
case
QEvent
::
ContextMenu
:
461
if
(
m_widgetZoomContextMenuEnabled
) {
462
// Calculate global position from scaled
463
QContextMenuEvent
*
ce
=
static_cast
<
QContextMenuEvent
*>(
event
);
464
const
QPointF
origin
=
mapToGlobal
(
QPoint
(0, 0)) -
scrollPosition
();
465
const
QPointF
pos
=
QPointF
(
origin
+ (
QPointF
(
ce
->
pos
()) *
zoomFactor
()));
466
showContextMenu
(
pos
.
toPoint
());
467
ce
->
accept
();
468
return
true
;
469
}
470
break
;
471
default
:
472
break
;
473
}
474
return
false
;
475
}
476
477
void
ZoomWidget
::
setItemAcceptDrops
(
bool
)
478
{
479
if
(
m_proxy
)
480
m_proxy
->
setAcceptDrops
(
true
);
481
}
482
483
bool
ZoomWidget
::
itemAcceptDrops
()
const
484
{
485
return
m_proxy
?
m_proxy
->
acceptDrops
() :
false
;
486
}
487
488
// Factory function for QGraphicsProxyWidgets which can be overwritten. Default creates a ZoomProxyWidget
489
QGraphicsProxyWidget
*
ZoomWidget
::
createProxyWidget
(
QGraphicsItem
*
parent
,
Qt
::
WindowFlags
wFlags
)
const
490
{
491
return
new
ZoomProxyWidget
(
parent
,
wFlags
);
492
}
493
494
void
ZoomWidget
::
dump
()
const
495
{
496
497
qDebug
() <<
"ZoomWidget::dump "
<<
geometry
() <<
" Viewport "
<<
viewport
()->
geometry
()
498
<<
"Scroll: "
<<
scrollPosition
() <<
"Transform: "
<<
transform
() <<
" SceneRect: "
<<
sceneRect
();
499
if
(
m_proxy
) {
500
qDebug
() <<
"Proxy Pos: "
<<
m_proxy
->
pos
() <<
"Proxy "
<<
m_proxy
->
size
()
501
<<
"\nProxy size hint"
502
<<
m_proxy
->
effectiveSizeHint
(
Qt
::
MinimumSize
)
503
<<
m_proxy
->
effectiveSizeHint
(
Qt
::
PreferredSize
)
504
<<
m_proxy
->
effectiveSizeHint
(
Qt
::
MaximumSize
)
505
<<
"\nTransform: "
<<
m_proxy
->
transform
()
506
<<
"\nWidget: "
<<
m_proxy
->
widget
()->
geometry
()
507
<<
"scaled"
<< (
zoomFactor
() *
m_proxy
->
widget
()->
size
());
508
}
509
}
510
511
}
// namespace qdesigner_internal
512
513
QT_END_NAMESPACE
qdesigner_internal::ZoomedEventFilterRedirector
Definition
zoomwidget.cpp:232
qdesigner_internal::ZoomedEventFilterRedirector::eventFilter
bool eventFilter(QObject *watched, QEvent *event) override
Filters events if this object has been installed as an event filter for the watched object.
Definition
zoomwidget.cpp:250
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
qdesigner_internal
Auxiliary methods to store/retrieve settings.
Definition
buddyeditor.cpp:67
qdesigner_internal::zoomedEventFilterRedirectorNameC
static constexpr auto zoomedEventFilterRedirectorNameC
Definition
zoomwidget.cpp:230
menuZoomList
static const int menuZoomList[]
Definition
zoomwidget.cpp:27
debugZoomWidget
@ debugZoomWidget
Definition
zoomwidget.cpp:25
qttools
src
designer
src
lib
shared
zoomwidget.cpp
Generated on
for Qt by
1.16.1