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