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
qquickcontextmenu.cpp
Go to the documentation of this file.
1
// Copyright (C) 2024 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
"qquickcontextmenu_p.h"
6
7
#
include
<
QtCore
/
qpointer
.
h
>
8
#
include
<
QtCore
/
qloggingcategory
.
h
>
9
#
include
<
QtQml
/
qqmlcomponent
.
h
>
10
#
include
<
QtQml
/
qqmlinfo
.
h
>
11
#
include
<
QtQuick
/
qquickwindow
.
h
>
12
#
include
<
QtQuick
/
private
/
qquickitem_p
.
h
>
13
#
include
<
QtQuickTemplates2
/
private
/
qquickdeferredexecute_p_p
.
h
>
14
#
include
<
QtQuickTemplates2
/
private
/
qquickmenu_p
.
h
>
15
#
include
<
QtQuickTemplates2
/
private
/
qquickmenu_p_p
.
h
>
16
#
include
<
QtQuickTemplates2
/
private
/
qquicktextarea_p
.
h
>
17
#
include
<
QtQuickTemplates2
/
private
/
qquicktextfield_p
.
h
>
18
19
QT_BEGIN_NAMESPACE
20
21
Q_STATIC_LOGGING_CATEGORY(lcContextMenu,
"qt.quick.controls.contextmenu"
)
22
23
/*!
24
\qmltype ContextMenu
25
\brief The ContextMenu attached type provides a way to open a context menu
26
in a platform-appropriate manner.
27
\inqmlmodule QtQuick.Controls
28
\ingroup qtquickcontrols-menus
29
\since 6.9
30
31
ContextMenu can be attached to any \l {QQuickItem}{item} in order to show a context menu
32
upon a platform-specific event, such as a right click or the context menu
33
key.
34
35
\snippet qtquickcontrols-contextmenu.qml root
36
37
\section1 Sharing context menus
38
39
It's possible to share a \l Menu amongst several attached context menu
40
objects. This allows reusing a single Menu when the items that need
41
context menus have data in common. For example:
42
43
\snippet qtquickcontrols-contextmenu-shared.qml file
44
45
\section1 Performance
46
47
ContextMenu lazily creates its \c Menu only when it's requested. If it
48
wasn't for this optimization, the \c Menu would be created when the
49
containing component is being loaded, which is typically at application
50
startup.
51
52
It is recommended not to give the \c Menu assigned to ContextMenu's \l menu
53
property an id when it's defined where it's assigned. Doing so prevents
54
this optimization. For example:
55
56
\snippet qtquickcontrols-contextmenu-id.qml root
57
58
The example in the \l {Sharing context menus} section works because the
59
\c Menu is defined separately from its assignment.
60
61
\section1 Interaction with other menus
62
63
If a \c Menu is opened via e.g. a \l TapHandler or other means, ContextMenu
64
will not open at the same time. This allows legacy applications that were
65
written before ContextMenu was introduced to continue working as expected.
66
67
\section1 Native menu support
68
69
ContextMenu is backed by a native menu on iOS.
70
71
\note if you assign your own \l menu, you must set
72
\l {Popup::popupType}{popupType} to \c {Popup.Native} to ensure native menu
73
support.
74
*/
75
76
/*!
77
\qmlsignal QtQuick.Controls::ContextMenu::requested(point position)
78
79
This signal is emitted when a context menu is requested.
80
81
If it was requested by a right mouse button click, \a position gives the
82
position of the click relative to the parent.
83
84
The example below shows how to programmatically open a context menu:
85
86
\snippet qtquickcontrols-contextmenu-onrequested.qml buttonAndMenu
87
88
If no menu is set, but this signal is connected, the context menu event
89
will be accepted and will not propagate.
90
91
\sa QContextMenuEvent::pos()
92
*/
93
94
class
QQuickContextMenuPrivate :
public
QObjectPrivate
95
{
96
public
:
97
Q_DECLARE_PUBLIC(QQuickContextMenu)
98
99
static
QQuickContextMenuPrivate *get(QQuickContextMenu *attachedObject)
100
{
101
return
attachedObject->d_func();
102
}
103
104
void
cancelMenu();
105
void
executeMenu(
bool
complete =
false
);
106
107
bool
isRequestedSignalConnected();
108
109
QQuickDeferredPointer<QQuickMenu> menu;
110
bool
complete =
false
;
111
};
112
113
static
const
QString
menuPropertyName
= QStringLiteral(
"menu"
);
114
115
void
QQuickContextMenuPrivate::cancelMenu()
116
{
117
Q_Q(QQuickContextMenu);
118
quickCancelDeferred(q, menuPropertyName);
119
}
120
121
void
QQuickContextMenuPrivate::executeMenu(
bool
complete)
122
{
123
Q_Q(QQuickContextMenu);
124
if
(menu.wasExecuted())
125
return
;
126
127
QQmlEngine *engine =
nullptr
;
128
auto
*parentItem = qobject_cast<QQuickItem *>(q->parent());
129
if
(parentItem) {
130
engine = qmlEngine(parentItem);
131
// In most cases, the above line will work, but if it doesn't,
132
// it could be because we're attached to the contentItem of the window.
133
// In that case, we'll be created before the contentItem has a context
134
// and hence an engine. However, the window will have one, so use that.
135
if
(!engine)
136
engine = qmlEngine(parentItem->window());
137
}
138
139
if
(!menu || complete)
140
quickBeginAttachedDeferred(q, menuPropertyName, menu, engine);
141
if
(complete)
142
quickCompleteAttachedDeferred(q, menuPropertyName, menu, engine);
143
}
144
145
bool
QQuickContextMenuPrivate::isRequestedSignalConnected()
146
{
147
Q_Q(QQuickContextMenu);
148
IS_SIGNAL_CONNECTED(q, QQuickContextMenu, requested, (QPointF));
149
}
150
151
QQuickContextMenu::QQuickContextMenu(QObject *parent)
152
: QObject(*(
new
QQuickContextMenuPrivate), parent)
153
{
154
Q_ASSERT(parent);
155
if
(parent->isQuickItemType()) {
156
auto
*itemPriv = QQuickItemPrivate::get(
static_cast
<QQuickItem *>(parent));
157
Q_ASSERT(itemPriv);
158
if
(QObject *oldMenu = itemPriv->setContextMenu(
this
))
159
qCWarning(lcContextMenu) <<
this
<<
"replaced"
<< oldMenu <<
"on"
<< parent;
160
}
else
{
161
qmlWarning(parent) <<
"ContextMenu must be attached to an Item"
;
162
}
163
}
164
165
QQuickContextMenu *QQuickContextMenu::qmlAttachedProperties(QObject *object)
166
{
167
return
new
QQuickContextMenu(object);
168
}
169
170
/*!
171
\qmlproperty Menu QtQuick.Controls::ContextMenu::menu
172
173
This property holds the context menu that will be opened. It can be set to
174
any \l Menu object.
175
176
\note The \l Menu assigned to this property cannot be given an id. See
177
\l {Sharing context menus} for more information.
178
*/
179
QQuickMenu *QQuickContextMenu::menu()
const
180
{
181
auto
*d =
const_cast
<QQuickContextMenuPrivate *>(d_func());
182
if
(!d->menu) {
183
qCDebug(lcContextMenu) <<
"creating menu via deferred execution"
184
<<
"- is component complete:"
<< d->complete;
185
d->executeMenu(d->complete);
186
}
187
return
d->menu;
188
}
189
190
void
QQuickContextMenu::setMenu(QQuickMenu *menu)
191
{
192
Q_D(QQuickContextMenu);
193
if
(!parent()->isQuickItemType())
194
return
;
195
196
if
(menu == d->menu)
197
return
;
198
199
if
(!d->menu.isExecuting())
200
d->cancelMenu();
201
202
d->menu = menu;
203
204
if
(!d->menu.isExecuting())
205
emit menuChanged();
206
}
207
208
void
QQuickContextMenu::classBegin()
209
{
210
}
211
212
void
QQuickContextMenu::componentComplete()
213
{
214
Q_D(QQuickContextMenu);
215
d->complete =
true
;
216
}
217
218
bool
QQuickContextMenu::event(QEvent *event)
219
{
220
Q_D(QQuickContextMenu);
221
switch
(event->type()) {
222
case
QEvent::ContextMenu: {
223
qCDebug(lcContextMenu) <<
this
<<
"handling"
<< event <<
"on behalf of"
<< parent();
224
225
auto
*attacheeItem = qobject_cast<QQuickItem *>(parent());
226
Q_ASSERT(attacheeItem);
227
const
auto
*contextMenuEvent =
static_cast
<QContextMenuEvent *>(event);
228
const
QPoint posRelativeToParent(attacheeItem->mapFromScene(contextMenuEvent->pos()).toPoint());
229
230
const
bool
isRequestedSignalConnected = d->isRequestedSignalConnected();
231
if
(isRequestedSignalConnected)
232
Q_EMIT requested(posRelativeToParent);
233
234
auto
*menu =
this
->menu();
235
if
(!menu) {
236
if
(isRequestedSignalConnected) {
237
qCDebug(lcContextMenu) <<
this
<<
"no menu instance but accepting event anyway"
238
<<
"since requested signal has connections"
;
239
event->accept();
240
return
true
;
241
}
242
243
// No menu set and requested isn't connected; let the event propagate
244
// onwards and do nothing.
245
return
QObject::event(event);
246
}
247
248
// On platforms like iOS, we want to use the native edit menu.
249
// TODO: test this on Android and desktop platforms (with popupType: Popup.Native)
250
if
(menu && QQuickMenuPrivate::get(menu)->resolvedPopupType() == QQuickPopup::Native
251
&& (qobject_cast<
const
QQuickTextField *>(attacheeItem)
252
|| qobject_cast<
const
QQuickTextArea *>(attacheeItem))) {
253
QQuickMenuPrivate::get(menu)->makeEditMenu();
254
}
255
256
menu->setParentItem(attacheeItem);
257
258
qCDebug(lcContextMenu) <<
this
<<
"showing"
<< menu <<
"at"
<< posRelativeToParent;
259
menu->popup(posRelativeToParent);
260
event->accept();
261
return
true
;
262
}
263
default
:
264
break
;
265
}
266
return
QObject::event(event);
267
}
268
269
QT_END_NAMESPACE
270
271
#
include
"moc_qquickcontextmenu_p.cpp"
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
menuPropertyName
static const QString menuPropertyName
Definition
qquickcontextmenu.cpp:113
qtdeclarative
src
quicktemplates
qquickcontextmenu.cpp
Generated on
for Qt by
1.18.0