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
qdesigner_toolbar.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
"qdesigner_toolbar_p.h"
5
#
include
"qdesigner_command_p.h"
6
#
include
"actionrepository_p.h"
7
#
include
"actionprovider_p.h"
8
#
include
"qdesigner_utils_p.h"
9
#
include
"qdesigner_objectinspector_p.h"
10
#
include
"promotiontaskmenu_p.h"
11
12
#
include
<
QtDesigner
/
abstractformwindow
.
h
>
13
#
include
<
QtDesigner
/
abstractpropertyeditor
.
h
>
14
#
include
<
QtDesigner
/
abstractformeditor
.
h
>
15
#
include
<
actionprovider_p
.
h
>
16
#
include
<
QtDesigner
/
qextensionmanager
.
h
>
17
#
include
<
QtDesigner
/
abstractwidgetfactory
.
h
>
18
19
#
include
<
QtWidgets
/
qapplication
.
h
>
20
#
include
<
QtWidgets
/
qtoolbutton
.
h
>
21
#
include
<
QtWidgets
/
qtoolbar
.
h
>
22
#
include
<
QtWidgets
/
qmenu
.
h
>
23
24
#
include
<
QtGui
/
qaction
.
h
>
25
#
include
<
QtGui
/
qevent
.
h
>
26
#
include
<
QtGui
/
qdrag
.
h
>
27
28
#
include
<
QtCore
/
qdebug
.
h
>
29
30
QT_BEGIN_NAMESPACE
31
32
using
namespace
Qt::StringLiterals;
33
34
using
ActionList = QList<QAction *>;
35
36
namespace
qdesigner_internal
{
37
// ------------------- ToolBarEventFilter
38
void
ToolBarEventFilter
::
install
(
QToolBar
*
tb
)
39
{
40
ToolBarEventFilter
*
tf
=
new
ToolBarEventFilter
(
tb
);
41
tb
->
installEventFilter
(
tf
);
42
tb
->
setAcceptDrops
(
true
);
// ### fake
43
}
44
45
ToolBarEventFilter
::
ToolBarEventFilter
(
QToolBar
*
tb
) :
46
QObject
(
tb
),
47
m_toolBar
(
tb
),
48
m_promotionTaskMenu
(
nullptr
)
49
{
50
}
51
52
ToolBarEventFilter
*
ToolBarEventFilter
::
eventFilterOf
(
const
QToolBar
*
tb
)
53
{
54
// Look for 1st order children only..otherwise, we might get filters of nested widgets
55
for
(
QObject
*
o
:
tb
->
children
()) {
56
if
(!
o
->
isWidgetType
())
57
if
(
ToolBarEventFilter
*
ef
=
qobject_cast
<
ToolBarEventFilter
*>(
o
))
58
return
ef
;
59
}
60
return
nullptr
;
61
}
62
63
bool
ToolBarEventFilter
::
eventFilter
(
QObject
*
watched
,
QEvent
*
event
)
64
{
65
if
(
watched
!=
m_toolBar
)
66
return
QObject
::
eventFilter
(
watched
,
event
);
67
68
bool
handled
=
false
;
69
switch
(
event
->
type
()) {
70
case
QEvent
::
ChildAdded
: {
71
// Children should not interact with the mouse
72
const
QChildEvent
*
ce
=
static_cast
<
const
QChildEvent
*>(
event
);
73
if
(
QWidget
*
w
=
qobject_cast
<
QWidget
*>(
ce
->
child
())) {
74
w
->
setAttribute
(
Qt
::
WA_TransparentForMouseEvents
,
true
);
75
w
->
setFocusPolicy
(
Qt
::
NoFocus
);
76
}
77
}
78
break
;
79
case
QEvent
::
ContextMenu
:
80
handled
=
handleContextMenuEvent
(
static_cast
<
QContextMenuEvent
*>(
event
));
81
break
;
82
case
QEvent
::
DragEnter
:
83
case
QEvent
::
DragMove
:
84
handled
=
handleDragEnterMoveEvent
(
static_cast
<
QDragMoveEvent
*>(
event
));
85
break
;
86
case
QEvent
::
DragLeave
:
87
handled
=
handleDragLeaveEvent
(
static_cast
<
QDragLeaveEvent
*>(
event
));
88
break
;
89
case
QEvent
::
Drop
:
90
handled
=
handleDropEvent
(
static_cast
<
QDropEvent
*>(
event
));
91
break
;
92
case
QEvent
::
MouseButtonPress
:
93
handled
=
handleMousePressEvent
(
static_cast
<
QMouseEvent
*>(
event
));
94
break
;
95
case
QEvent
::
MouseButtonRelease
:
96
handled
=
handleMouseReleaseEvent
(
static_cast
<
QMouseEvent
*>(
event
));
97
break
;
98
case
QEvent
::
MouseMove
:
99
handled
=
handleMouseMoveEvent
(
static_cast
<
QMouseEvent
*>(
event
));
100
break
;
101
default
:
102
break
;
103
}
104
105
return
handled
||
QObject
::
eventFilter
(
watched
,
event
);
106
}
107
108
ActionList
ToolBarEventFilter
::
contextMenuActions
(
const
QPoint
&
globalPos
)
109
{
110
ActionList
rc
;
111
const
int
index
=
actionIndexAt
(
m_toolBar
,
m_toolBar
->
mapFromGlobal
(
globalPos
),
m_toolBar
->
orientation
());
112
const
auto
actions
=
m_toolBar
->
actions
();
113
QAction
*
action
=
index
!= -1 ?
actions
.
at
(
index
) : 0;
114
QVariant
itemData
;
115
116
// Insert before
117
if
(
action
&&
index
!= 0 && !
action
->
isSeparator
()) {
118
QAction
*
newSeperatorAct
=
new
QAction
(
tr
(
"Insert Separator before '%1'"
).
arg
(
action
->
objectName
()),
nullptr
);
119
itemData
.
setValue
(
action
);
120
newSeperatorAct
->
setData
(
itemData
);
121
connect
(
newSeperatorAct
, &
QAction
::
triggered
,
this
, &
ToolBarEventFilter
::
slotInsertSeparator
);
122
rc
.
push_back
(
newSeperatorAct
);
123
}
124
125
// Append separator
126
if
(
actions
.
isEmpty
() || !
actions
.
constLast
()->
isSeparator
()) {
127
QAction
*
newSeperatorAct
=
new
QAction
(
tr
(
"Append Separator"
),
nullptr
);
128
itemData
.
setValue
(
static_cast
<
QAction
*>(
nullptr
));
129
newSeperatorAct
->
setData
(
itemData
);
130
connect
(
newSeperatorAct
, &
QAction
::
triggered
,
this
, &
ToolBarEventFilter
::
slotInsertSeparator
);
131
rc
.
push_back
(
newSeperatorAct
);
132
}
133
// Promotion
134
if
(!
m_promotionTaskMenu
)
135
m_promotionTaskMenu
=
new
PromotionTaskMenu
(
m_toolBar
,
PromotionTaskMenu
::
ModeSingleWidget
,
this
);
136
m_promotionTaskMenu
->
addActions
(
formWindow
(),
PromotionTaskMenu
::
LeadingSeparator
|
PromotionTaskMenu
::
TrailingSeparator
,
rc
);
137
// Remove
138
if
(
action
) {
139
QAction
*
a
=
new
QAction
(
tr
(
"Remove action '%1'"
).
arg
(
action
->
objectName
()),
nullptr
);
140
itemData
.
setValue
(
action
);
141
a
->
setData
(
itemData
);
142
connect
(
a
, &
QAction
::
triggered
,
this
, &
ToolBarEventFilter
::
slotRemoveSelectedAction
);
143
rc
.
push_back
(
a
);
144
}
145
146
QAction
*
remove_toolbar
=
new
QAction
(
tr
(
"Remove Toolbar '%1'"
).
arg
(
m_toolBar
->
objectName
()),
nullptr
);
147
connect
(
remove_toolbar
, &
QAction
::
triggered
,
this
, &
ToolBarEventFilter
::
slotRemoveToolBar
);
148
rc
.
push_back
(
remove_toolbar
);
149
return
rc
;
150
}
151
152
bool
ToolBarEventFilter
::
handleContextMenuEvent
(
QContextMenuEvent
*
event
)
153
{
154
event
->
accept
();
155
156
const
QPoint
globalPos
=
event
->
globalPos
();
157
const
ActionList
al
=
contextMenuActions
(
event
->
globalPos
());
158
159
QMenu
menu
(
nullptr
);
160
for
(
auto
*
a
:
al
)
161
menu
.
addAction
(
a
);
162
menu
.
exec
(
globalPos
);
163
return
true
;
164
}
165
166
void
ToolBarEventFilter
::
slotRemoveSelectedAction
()
167
{
168
QAction
*
action
=
qobject_cast
<
QAction
*>(
sender
());
169
if
(!
action
)
170
return
;
171
172
QAction
*
a
=
qvariant_cast
<
QAction
*>(
action
->
data
());
173
Q_ASSERT
(
a
!=
nullptr
);
174
175
QDesignerFormWindowInterface
*
fw
=
formWindow
();
176
Q_ASSERT
(
fw
);
177
178
const
ActionList
actions
=
m_toolBar
->
actions
();
179
const
int
pos
=
actions
.
indexOf
(
a
);
180
QAction
*
action_before
=
nullptr
;
181
if
(
pos
!= -1 &&
actions
.
size
() >
pos
+ 1)
182
action_before
=
actions
.
at
(
pos
+ 1);
183
184
RemoveActionFromCommand
*
cmd
=
new
RemoveActionFromCommand
(
fw
);
185
cmd
->
init
(
m_toolBar
,
a
,
action_before
);
186
fw
->
commandHistory
()->
push
(
cmd
);
187
}
188
189
void
ToolBarEventFilter
::
slotRemoveToolBar
()
190
{
191
QDesignerFormWindowInterface
*
fw
=
formWindow
();
192
Q_ASSERT
(
fw
);
193
DeleteToolBarCommand
*
cmd
=
new
DeleteToolBarCommand
(
fw
);
194
cmd
->
init
(
m_toolBar
);
195
fw
->
commandHistory
()->
push
(
cmd
);
196
}
197
198
void
ToolBarEventFilter
::
slotInsertSeparator
()
199
{
200
QDesignerFormWindowInterface
*
fw
=
formWindow
();
201
QAction
*
theSender
=
qobject_cast
<
QAction
*>(
sender
());
202
QAction
*
previous
=
qvariant_cast
<
QAction
*>(
theSender
->
data
());
203
fw
->
beginCommand
(
tr
(
"Insert Separator"
));
204
QAction
*
action
=
createAction
(
fw
, u"separator"_s,
true
);
205
InsertActionIntoCommand
*
cmd
=
new
InsertActionIntoCommand
(
fw
);
206
cmd
->
init
(
m_toolBar
,
action
,
previous
);
207
fw
->
commandHistory
()->
push
(
cmd
);
208
fw
->
endCommand
();
209
}
210
211
QDesignerFormWindowInterface
*
ToolBarEventFilter
::
formWindow
()
const
212
{
213
return
QDesignerFormWindowInterface
::
findFormWindow
(
m_toolBar
);
214
}
215
216
QAction
*
ToolBarEventFilter
::
createAction
(
QDesignerFormWindowInterface
*
fw
,
const
QString
&
objectName
,
bool
separator
)
217
{
218
QAction
*
action
=
new
QAction
(
fw
);
219
fw
->
core
()->
widgetFactory
()->
initialize
(
action
);
220
if
(
separator
)
221
action
->
setSeparator
(
true
);
222
223
action
->
setObjectName
(
objectName
);
224
fw
->
ensureUniqueObjectName
(
action
);
225
226
qdesigner_internal
::
AddActionCommand
*
cmd
=
new
qdesigner_internal
::
AddActionCommand
(
fw
);
227
cmd
->
init
(
action
);
228
fw
->
commandHistory
()->
push
(
cmd
);
229
230
return
action
;
231
}
232
233
void
ToolBarEventFilter
::
adjustDragIndicator
(
const
QPoint
&
pos
)
234
{
235
if
(
QDesignerFormWindowInterface
*
fw
=
formWindow
()) {
236
QDesignerFormEditorInterface
*
core
=
fw
->
core
();
237
if
(
QDesignerActionProviderExtension
*
a
=
qt_extension
<
QDesignerActionProviderExtension
*>(
core
->
extensionManager
(),
m_toolBar
))
238
a
->
adjustIndicator
(
pos
);
239
}
240
}
241
242
void
ToolBarEventFilter
::
hideDragIndicator
()
243
{
244
adjustDragIndicator
(
QPoint
(-1, -1));
245
}
246
247
bool
ToolBarEventFilter
::
handleMousePressEvent
(
QMouseEvent
*
event
)
248
{
249
if
(
event
->
button
() !=
Qt
::
LeftButton
||
withinHandleArea
(
m_toolBar
,
event
->
position
().
toPoint
()))
250
return
false
;
251
252
if
(
QDesignerFormWindowInterface
*
fw
=
formWindow
()) {
253
QDesignerFormEditorInterface
*
core
=
fw
->
core
();
254
// Keep selection in sync
255
fw
->
clearSelection
(
false
);
256
if
(
QDesignerObjectInspector
*
oi
=
qobject_cast
<
QDesignerObjectInspector
*>(
core
->
objectInspector
())) {
257
oi
->
clearSelection
();
258
oi
->
selectObject
(
m_toolBar
);
259
}
260
core
->
propertyEditor
()->
setObject
(
m_toolBar
);
261
}
262
const
auto
pos
=
m_toolBar
->
mapFromGlobal
(
event
->
globalPosition
().
toPoint
());
263
if
(
actionIndexAt
(
m_toolBar
,
pos
,
m_toolBar
->
orientation
()) != -1) {
264
m_startPosition
=
pos
;
265
event
->
accept
();
266
return
true
;
267
}
268
return
false
;
269
}
270
271
bool
ToolBarEventFilter
::
handleMouseReleaseEvent
(
QMouseEvent
*
event
)
272
{
273
if
(
event
->
button
() !=
Qt
::
LeftButton
||
m_startPosition
.
isNull
() ||
withinHandleArea
(
m_toolBar
,
event
->
position
().
toPoint
()))
274
return
false
;
275
276
// Accept the event, otherwise, form window selection will trigger
277
m_startPosition
=
QPoint
();
278
event
->
accept
();
279
return
true
;
280
}
281
282
bool
ToolBarEventFilter
::
handleMouseMoveEvent
(
QMouseEvent
*
event
)
283
{
284
if
(
m_startPosition
.
isNull
() ||
withinHandleArea
(
m_toolBar
,
event
->
position
().
toPoint
()))
285
return
false
;
286
287
const
QPoint
pos
=
m_toolBar
->
mapFromGlobal
(
event
->
globalPosition
().
toPoint
());
288
if
((
pos
-
m_startPosition
).
manhattanLength
() >
QApplication
::
startDragDistance
()
289
&&
startDrag
(
m_startPosition
,
event
->
modifiers
())) {
290
m_startPosition
=
QPoint
();
291
event
->
accept
();
292
return
true
;
293
}
294
return
false
;
295
}
296
297
bool
ToolBarEventFilter
::
handleDragEnterMoveEvent
(
QDragMoveEvent
*
event
)
298
{
299
const
ActionRepositoryMimeData
*
d
=
qobject_cast
<
const
ActionRepositoryMimeData
*>(
event
->
mimeData
());
300
if
(!
d
)
301
return
false
;
302
303
if
(
d
->
actionList
().
isEmpty
()) {
304
event
->
ignore
();
305
hideDragIndicator
();
306
return
true
;
307
}
308
309
QAction
*
action
=
d
->
actionList
().
first
();
310
if
(!
action
||
action
->
menu
() ||
m_toolBar
->
actions
().
contains
(
action
) || !
Utils
::
isObjectAncestorOf
(
formWindow
()->
mainContainer
(),
action
)) {
311
event
->
ignore
();
312
hideDragIndicator
();
313
return
true
;
314
}
315
316
d
->
accept
(
event
);
317
adjustDragIndicator
(
event
->
position
().
toPoint
());
318
return
true
;
319
}
320
321
bool
ToolBarEventFilter
::
handleDragLeaveEvent
(
QDragLeaveEvent
*)
322
{
323
hideDragIndicator
();
324
return
false
;
325
}
326
327
bool
ToolBarEventFilter
::
handleDropEvent
(
QDropEvent
*
event
)
328
{
329
const
ActionRepositoryMimeData
*
d
=
qobject_cast
<
const
ActionRepositoryMimeData
*>(
event
->
mimeData
());
330
if
(!
d
)
331
return
false
;
332
333
if
(
d
->
actionList
().
isEmpty
()) {
334
event
->
ignore
();
335
hideDragIndicator
();
336
return
true
;
337
}
338
339
QAction
*
action
=
d
->
actionList
().
first
();
340
341
const
ActionList
actions
=
m_toolBar
->
actions
();
342
if
(!
action
||
actions
.
contains
(
action
)) {
343
event
->
ignore
();
344
hideDragIndicator
();
345
return
true
;
346
}
347
348
// Try to find action to 'insert before'. Click on action or in free area, else ignore.
349
QAction
*
beforeAction
=
nullptr
;
350
const
QPoint
pos
=
event
->
position
().
toPoint
();
351
const
int
index
=
actionIndexAt
(
m_toolBar
,
pos
,
m_toolBar
->
orientation
());
352
if
(
index
!= -1) {
353
beforeAction
=
actions
.
at
(
index
);
354
}
else
{
355
if
(!
freeArea
(
m_toolBar
).
contains
(
pos
)) {
356
event
->
ignore
();
357
hideDragIndicator
();
358
return
true
;
359
}
360
}
361
362
event
->
acceptProposedAction
();
363
QDesignerFormWindowInterface
*
fw
=
formWindow
();
364
InsertActionIntoCommand
*
cmd
=
new
InsertActionIntoCommand
(
fw
);
365
cmd
->
init
(
m_toolBar
,
action
,
beforeAction
);
366
fw
->
commandHistory
()->
push
(
cmd
);
367
hideDragIndicator
();
368
return
true
;
369
}
370
371
bool
ToolBarEventFilter
::
startDrag
(
const
QPoint
&
pos
,
Qt
::
KeyboardModifiers
modifiers
)
372
{
373
const
int
index
=
actionIndexAt
(
m_toolBar
,
pos
,
m_toolBar
->
orientation
());
374
if
(
index
== - 1)
375
return
false
;
376
377
const
ActionList
actions
=
m_toolBar
->
actions
();
378
QAction
*
action
=
actions
.
at
(
index
);
379
QDesignerFormWindowInterface
*
fw
=
formWindow
();
380
381
const
Qt
::
DropAction
dropAction
= (
modifiers
&
Qt
::
ControlModifier
) ?
Qt
::
CopyAction
:
Qt
::
MoveAction
;
382
if
(
dropAction
==
Qt
::
MoveAction
) {
383
RemoveActionFromCommand
*
cmd
=
new
RemoveActionFromCommand
(
fw
);
384
const
int
nextIndex
=
index
+ 1;
385
QAction
*
nextAction
=
nextIndex
<
actions
.
size
() ?
actions
.
at
(
nextIndex
) : 0;
386
cmd
->
init
(
m_toolBar
,
action
,
nextAction
);
387
fw
->
commandHistory
()->
push
(
cmd
);
388
}
389
390
QDrag
*
drag
=
new
QDrag
(
m_toolBar
);
391
drag
->
setPixmap
(
ActionRepositoryMimeData
::
actionDragPixmap
(
action
));
392
drag
->
setMimeData
(
new
ActionRepositoryMimeData
(
action
,
dropAction
));
393
394
if
(
drag
->
exec
(
dropAction
) ==
Qt
::
IgnoreAction
) {
395
hideDragIndicator
();
396
if
(
dropAction
==
Qt
::
MoveAction
) {
397
const
ActionList
currentActions
=
m_toolBar
->
actions
();
398
QAction
*
previous
=
nullptr
;
399
if
(
index
>= 0 &&
index
<
currentActions
.
size
())
400
previous
=
currentActions
.
at
(
index
);
401
InsertActionIntoCommand
*
cmd
=
new
InsertActionIntoCommand
(
fw
);
402
cmd
->
init
(
m_toolBar
,
action
,
previous
);
403
fw
->
commandHistory
()->
push
(
cmd
);
404
}
405
}
406
return
true
;
407
}
408
409
QAction
*
ToolBarEventFilter
::
actionAt
(
const
QToolBar
*
tb
,
const
QPoint
&
pos
)
410
{
411
const
int
index
=
actionIndexAt
(
tb
,
pos
,
tb
->
orientation
());
412
if
(
index
== -1)
413
return
nullptr
;
414
return
tb
->
actions
().
at
(
index
);
415
}
416
417
//that's a trick to get access to the initStyleOption which is a protected member
418
class
FriendlyToolBar
:
public
QToolBar
{
419
public
:
420
friend
class
ToolBarEventFilter;
421
};
422
423
QRect
ToolBarEventFilter
::
handleArea
(
const
QToolBar
*
tb
)
424
{
425
QStyleOptionToolBar
opt
;
426
static_cast
<
const
FriendlyToolBar
*>(
tb
)->
initStyleOption
(&
opt
);
427
return
tb
->
style
()->
subElementRect
(
QStyle
::
SE_ToolBarHandle
, &
opt
,
tb
);
428
}
429
430
bool
ToolBarEventFilter
::
withinHandleArea
(
const
QToolBar
*
tb
,
const
QPoint
&
pos
)
431
{
432
return
handleArea
(
tb
).
contains
(
pos
);
433
}
434
435
// Determine the free area behind the last action.
436
QRect
ToolBarEventFilter
::
freeArea
(
const
QToolBar
*
tb
)
437
{
438
QRect
rc
=
QRect
(
QPoint
(0, 0),
tb
->
size
());
439
const
ActionList
actionList
=
tb
->
actions
();
440
QRect
exclusionRectangle
=
actionList
.
isEmpty
()
441
?
handleArea
(
tb
) :
tb
->
actionGeometry
(
actionList
.
constLast
());
442
switch
(
tb
->
orientation
()) {
443
case
Qt
::
Horizontal
:
444
switch
(
tb
->
layoutDirection
()) {
445
case
Qt
::
LayoutDirectionAuto
:
// Should never happen
446
case
Qt
::
LeftToRight
:
447
rc
.
setX
(
exclusionRectangle
.
right
() + 1);
448
break
;
449
case
Qt
::
RightToLeft
:
450
rc
.
setRight
(
exclusionRectangle
.
x
());
451
break
;
452
}
453
break
;
454
case
Qt
::
Vertical
:
455
rc
.
setY
(
exclusionRectangle
.
bottom
() + 1);
456
break
;
457
}
458
return
rc
;
459
}
460
461
}
462
463
QT_END_NAMESPACE
qdesigner_internal::FriendlyToolBar
Definition
qdesigner_toolbar.cpp:418
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
qttools
src
designer
src
lib
shared
qdesigner_toolbar.cpp
Generated on Sat Sep 21 2024 00:50:36 for Qt by
1.12.0