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
qquicktreeviewdelegate.cpp
Go to the documentation of this file.
1
// Copyright (C) 2021 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
"qquicktreeviewdelegate_p.h"
6
7
#
include
<
QtQuickTemplates2
/
private
/
qquickitemdelegate_p_p
.
h
>
8
#
include
<
QtQuick
/
private
/
qquicktaphandler_p
.
h
>
9
#
include
<
QtQuick
/
private
/
qquicktreeview_p_p
.
h
>
10
11
#
include
<
QtCore
/
qpointer
.
h
>
12
13
QT_BEGIN_NAMESPACE
14
15
/*!
16
\qmltype TreeViewDelegate
17
\inherits ItemDelegate
18
\inqmlmodule QtQuick.Controls
19
\since 6.3
20
\ingroup qtquickcontrols-delegates
21
\brief A delegate that can be assigned to a TreeView.
22
23
\image qtquickcontrols-treeviewdelegate.png
24
{Tree view displaying hierarchical data using a tree view delegate}
25
26
A TreeViewDelegate is a delegate that can be assigned to the
27
\l {TableView::delegate} {delegate property} of a \l TreeView.
28
It renders the tree, as well as the other columns, in the view
29
using the application style.
30
31
\qml
32
TreeView {
33
anchors.fill: parent
34
delegate: TreeViewDelegate {}
35
// The model needs to be a QAbstractItemModel
36
// model: yourTreeModel
37
}
38
\endqml
39
40
TreeViewDelegate inherits \l ItemDelegate, which means that
41
it's composed of three items: a \l[QML]{Control::}{background},
42
a \l [QML]{Control::}{contentItem}, and an
43
\l [QML]{AbstractButton::}{indicator}. TreeViewDelegate takes care
44
of \l {indentation}{indenting} the contentItem and the indicator according
45
their location in the tree. The indicator will only be visible if the
46
delegate item is inside the \l {isTreeNode}{tree column}, and renders
47
a model item \l {hasChildren}{with children}.
48
49
If you change the indicator, it will no longer be indented by default.
50
Instead you need to indent it yourself by setting the
51
\l [QML] {Item::x}{x position} of the indicator, taking the \l depth and
52
\l indentation into account. Below is an example of how to do that:
53
54
\qml
55
TreeViewDelegate {
56
indicator: Item {
57
x: leftMargin + (depth * indentation)
58
}
59
}
60
\endqml
61
62
The position of the contentItem is controlled with \l [QML]{Control::}{padding}.
63
This means that you can change the contentItem without dealing with indentation.
64
But it also means that you should avoid changing padding to something else, as
65
that will remove the indentation. The space to the left of the indicator is instead
66
controlled with \l leftMargin. The space between the indicator and the contentItem
67
is controlled with \l [QML]{Control::}{spacing}. And the space to the right of the
68
contentItem is controlled with \l rightMargin.
69
70
\section2 Interacting with pointers
71
TreeViewDelegate inherits \l ItemDelegate. This means that it will emit signals
72
such as \l {AbstractButton::clicked()}{clicked} when the user clicks on the delegate.
73
If needed, you could connect to that signal to implement application specific
74
functionality, in addition to the default expand/collapse behavior (and even set \l
75
{TableView::pointerNavigationEnabled}{pointerNavigationEnabled} to \c false, to
76
disable the default behavior as well).
77
78
But the ItemDelegate API does not give you information about the position of the
79
click, or which modifiers are being held. If this is needed, a better approach would
80
be to use pointer handlers, for example:
81
82
\qml
83
TreeView {
84
id: treeView
85
delegate: TreeViewDelegate {
86
TapHandler {
87
acceptedButtons: Qt.RightButton
88
onTapped: someContextMenu.open()
89
}
90
91
TapHandler {
92
acceptedModifiers: Qt.ControlModifier
93
onTapped: {
94
if (treeView.isExpanded(row))
95
treeView.collapseRecursively(row)
96
else
97
treeView.expandRecursively(row)
98
}
99
}
100
}
101
}
102
\endqml
103
104
\note If you want to disable the default behavior that occurs when the
105
user clicks on the delegate (like changing the current index), you can set
106
\l {TableView::pointerNavigationEnabled}{pointerNavigationEnabled} to \c false.
107
108
\section2 Editing nodes in the tree
109
TreeViewDelegate has a default \l {TableView::editDelegate}{edit delegate}
110
assigned. If \l TreeView has \l {TableView::editTriggers}{edit triggers}
111
set, and the \l {TableView::model}{model} has support for
112
\l {Editing cells} {editing model items}, then the user can activate any of
113
the edit triggers to edit the text of the \l {TreeViewDelegate::current}{current}
114
tree node.
115
116
The default edit delegate will try to use the \c {Qt.EditRole} to read and
117
write data to the \l {TableView::model}{model}.
118
If \l QAbstractItemModel::data() returns an empty string for this role, then
119
\c {Qt.DisplayRole} will be used instead.
120
121
You can always assign your own custom edit delegate to
122
\l {TableView::editDelegate}{TableView.editDelegate} if you have needs
123
outside what the default edit delegate offers.
124
125
\sa TreeView
126
*/
127
128
/*!
129
\qmlproperty TreeView QtQuick.Controls::TreeViewDelegate::treeView
130
131
This property points to the \l TreeView that contains the delegate item.
132
*/
133
134
/*!
135
\qmlproperty bool QtQuick.Controls::TreeViewDelegate::hasChildren
136
137
This property is \c true if the model item drawn by the delegate
138
has children in the model.
139
*/
140
141
/*!
142
\qmlproperty bool QtQuick.Controls::TreeViewDelegate::isTreeNode
143
144
This property is \c true if the delegate item draws a node in the tree.
145
Only one column in the view will be used to draw the tree, and
146
therefore, only delegate items in that column will have this
147
property set to \c true.
148
149
A node in the tree is \l{indentation}{indented} according to its \c depth, and show
150
an \l [QML]{AbstractButton::}{indicator} if hasChildren is \c true. Delegate items
151
in other columns will have this property set to \c false.
152
*/
153
154
/*!
155
\qmlproperty bool QtQuick.Controls::TreeViewDelegate::expanded
156
157
This property is \c true if the model item drawn by the delegate
158
is expanded in the view.
159
*/
160
161
/*!
162
\qmlproperty int QtQuick.Controls::TreeViewDelegate::depth
163
164
This property holds the depth of the model item drawn by the delegate.
165
The depth of a model item is the same as the number of ancestors
166
it has in the model.
167
*/
168
169
/*!
170
\qmlproperty bool QtQuick.Controls::TreeViewDelegate::current
171
172
This property holds if the delegate represent the
173
\l {QItemSelectionModel::currentIndex()}{current index}
174
in the \l {TableView::selectionModel}{selection model}.
175
*/
176
177
/*!
178
\qmlproperty bool QtQuick.Controls::TreeViewDelegate::selected
179
180
This property holds if the delegate represent a
181
\l {QItemSelectionModel::selection()}{selected index}
182
in the \l {TableView::selectionModel}{selection model}.
183
*/
184
185
/*!
186
\qmlproperty bool QtQuick.Controls::TreeViewDelegate::editing
187
\since 6.5
188
189
This property holds if the delegate is being
190
\l {Editing cells}{edited.}
191
*/
192
193
/*!
194
\qmlproperty real QtQuick.Controls::TreeViewDelegate::indentation
195
196
This property holds the space a child is indented horizontally
197
relative to its parent.
198
*/
199
200
/*!
201
\qmlproperty real QtQuick.Controls::TreeViewDelegate::leftMargin
202
203
This property holds the space between the left edge of the view
204
and the left edge of the indicator (in addition to indentation).
205
If no indicator is visible, the space will be between the left
206
edge of the view and the left edge of the contentItem.
207
208
\sa rightMargin, indentation, {QtQuick.Controls::Control::}{spacing}
209
*/
210
211
/*!
212
\qmlproperty real QtQuick.Controls::TreeViewDelegate::rightMargin
213
214
This property holds the space between the right edge of the view
215
and the right edge of the contentItem.
216
217
\sa leftMargin, indentation, {QtQuick.Controls::Control::}{spacing}
218
*/
219
220
using
namespace
Qt::Literals::StringLiterals;
221
222
class
QQuickTreeViewDelegatePrivate
:
public
QQuickItemDelegatePrivate
223
{
224
public
:
225
Q_DECLARE_PUBLIC(QQuickTreeViewDelegate)
226
227
void
updateIndicatorVisibility
();
228
void
updateIndicatorPointerHandlers
();
229
void
toggleExpanded
();
230
QPalette
defaultPalette
()
const
override
;
231
232
public
:
233
QPointer
<
QQuickTreeView
>
m_treeView
;
234
QPointer
<
QQuickTapHandler
>
m_tapHandlerOnIndicator
;
235
qreal
m_indentation
= 18;
236
qreal
m_leftMargin
= 0;
237
qreal
m_rightMargin
= 0;
238
bool
m_isTreeNode
=
false
;
239
bool
m_expanded
=
false
;
240
bool
m_current
=
false
;
241
bool
m_selected
=
false
;
242
bool
m_editing
=
false
;
243
bool
m_hasChildren
=
false
;
244
bool
m_pressOnTopOfIndicator
=
false
;
245
int
m_depth
= 0;
246
};
247
248
void
QQuickTreeViewDelegatePrivate
::
toggleExpanded
()
249
{
250
Q_Q(QQuickTreeViewDelegate);
251
252
auto
view = q->treeView();
253
if
(!view)
254
return
;
255
if
(!view->pointerNavigationEnabled())
256
return
;
257
258
const
int
row = qmlContext(q)->contextProperty(u"row"_s).toInt();
259
view->toggleExpanded(row);
260
}
261
262
void
QQuickTreeViewDelegatePrivate
::
updateIndicatorPointerHandlers
()
263
{
264
Q_Q(QQuickTreeViewDelegate);
265
266
// Remove the tap handler that was installed
267
// on the previous indicator
268
delete
m_tapHandlerOnIndicator.data();
269
270
auto
indicator = q->indicator();
271
if
(!indicator)
272
return
;
273
274
m_tapHandlerOnIndicator =
new
QQuickTapHandler(indicator);
275
m_tapHandlerOnIndicator->setAcceptedModifiers(Qt::NoModifier);
276
// Work-around to block taps from passing through to TreeView.
277
m_tapHandlerOnIndicator->setGesturePolicy(QQuickTapHandler::ReleaseWithinBounds);
278
connect(m_tapHandlerOnIndicator, &QQuickTapHandler::tapped,
this
, &
QQuickTreeViewDelegatePrivate
::
toggleExpanded
);
279
}
280
281
void
QQuickTreeViewDelegatePrivate
::
updateIndicatorVisibility
()
282
{
283
Q_Q(QQuickTreeViewDelegate);
284
285
if
(
auto
indicator = q_func()->indicator()) {
286
const
bool
insideDelegateBounds = indicator->x() + indicator->width() < q->width();
287
indicator->setVisible(
m_isTreeNode
&&
m_hasChildren
&& insideDelegateBounds);
288
}
289
}
290
291
QQuickTreeViewDelegate::QQuickTreeViewDelegate(QQuickItem *parent)
292
: QQuickItemDelegate(*(
new
QQuickTreeViewDelegatePrivate), parent)
293
{
294
Q_D(QQuickTreeViewDelegate);
295
296
auto
tapHandler =
new
QQuickTapHandler(
this
);
297
tapHandler->setAcceptedModifiers(Qt::NoModifier);
298
QObjectPrivate::connect(
this
, &QQuickAbstractButton::indicatorChanged, d, &QQuickTreeViewDelegatePrivate::updateIndicatorPointerHandlers);
299
300
// Since we override mousePressEvent to avoid QQuickAbstractButton from blocking
301
// pointer handlers, we inform the button about its pressed state from the tap
302
// handler instead. This will ensure that we emit button signals like
303
// pressed, clicked, and doubleClicked.
304
connect(tapHandler, &QQuickTapHandler::pressedChanged,
this
, [
this
, d, tapHandler] {
305
auto
view = treeView();
306
if
(view && !view->pointerNavigationEnabled())
307
return
;
308
309
const
QQuickHandlerPoint p = tapHandler->point();
310
if
(tapHandler->isPressed())
311
d->handlePress(p.position(), 0);
312
else
if
(tapHandler->tapCount() > 0)
313
d->handleRelease(p.position(), 0);
314
else
315
d->handleUngrab();
316
317
if
(tapHandler->tapCount() > 1 && !tapHandler->isPressed())
318
emit doubleClicked();
319
});
320
}
321
322
void
QQuickTreeViewDelegate::geometryChange(
const
QRectF &newGeometry,
const
QRectF &oldGeometry)
323
{
324
Q_D(QQuickTreeViewDelegate);
325
326
QQuickItemDelegate::geometryChange(newGeometry, oldGeometry);
327
d->updateIndicatorVisibility();
328
}
329
330
void
QQuickTreeViewDelegate::mousePressEvent(QMouseEvent *event)
331
{
332
Q_D(QQuickTreeViewDelegate);
333
334
const
auto
view = d->m_treeView;
335
if
(view && view->pointerNavigationEnabled()) {
336
// Ignore mouse events so that we don't block our own pointer handlers, or
337
// pointer handlers in e.g TreeView, TableView, or SelectionRectangle. Instead
338
// we call out to the needed mouse handling functions in QAbstractButton directly
339
// from our pointer handlers, to ensure that continue to work as a button.
340
event->ignore();
341
return
;
342
}
343
344
QQuickItemDelegate::mousePressEvent(event);
345
}
346
347
QPalette
QQuickTreeViewDelegatePrivate
::
defaultPalette
()
const
348
{
349
return
QQuickTheme::palette(QQuickTheme::ItemView);
350
}
351
352
QFont QQuickTreeViewDelegate::defaultFont()
const
353
{
354
return
QQuickTheme::font(QQuickTheme::ItemView);
355
}
356
357
qreal QQuickTreeViewDelegate::indentation()
const
358
{
359
return
d_func()->m_indentation;
360
}
361
362
void
QQuickTreeViewDelegate::setIndentation(qreal indentation)
363
{
364
Q_D(QQuickTreeViewDelegate);
365
if
(qFuzzyCompare(d->m_indentation, indentation))
366
return
;
367
368
d->m_indentation = indentation;
369
emit indentationChanged();
370
}
371
372
bool
QQuickTreeViewDelegate::isTreeNode()
const
373
{
374
return
d_func()->m_isTreeNode;
375
}
376
377
void
QQuickTreeViewDelegate::setIsTreeNode(
bool
isTreeNode)
378
{
379
Q_D(QQuickTreeViewDelegate);
380
if
(d->m_isTreeNode == isTreeNode)
381
return
;
382
383
d->m_isTreeNode = isTreeNode;
384
d->updateIndicatorVisibility();
385
emit isTreeNodeChanged();
386
}
387
388
bool
QQuickTreeViewDelegate::hasChildren()
const
389
{
390
return
d_func()->m_hasChildren;
391
}
392
393
void
QQuickTreeViewDelegate::setHasChildren(
bool
hasChildren)
394
{
395
Q_D(QQuickTreeViewDelegate);
396
if
(d->m_hasChildren == hasChildren)
397
return
;
398
399
d->m_hasChildren = hasChildren;
400
d->updateIndicatorVisibility();
401
emit hasChildrenChanged();
402
}
403
404
bool
QQuickTreeViewDelegate::expanded()
const
405
{
406
return
d_func()->m_expanded;
407
}
408
409
void
QQuickTreeViewDelegate::setExpanded(
bool
expanded)
410
{
411
Q_D(QQuickTreeViewDelegate);
412
if
(d->m_expanded == expanded)
413
return
;
414
415
d->m_expanded = expanded;
416
emit expandedChanged();
417
}
418
419
bool
QQuickTreeViewDelegate::current()
const
420
{
421
return
d_func()->m_current;
422
}
423
424
void
QQuickTreeViewDelegate::setCurrent(
bool
current)
425
{
426
Q_D(QQuickTreeViewDelegate);
427
if
(d->m_current == current)
428
return
;
429
430
d->m_current = current;
431
emit currentChanged();
432
}
433
434
bool
QQuickTreeViewDelegate::selected()
const
435
{
436
return
d_func()->m_selected;
437
}
438
439
void
QQuickTreeViewDelegate::setSelected(
bool
selected)
440
{
441
Q_D(QQuickTreeViewDelegate);
442
if
(d->m_selected == selected)
443
return
;
444
445
d->m_selected = selected;
446
emit selectedChanged();
447
}
448
449
bool
QQuickTreeViewDelegate::editing()
const
450
{
451
return
d_func()->m_editing;
452
}
453
454
void
QQuickTreeViewDelegate::setEditing(
bool
editing)
455
{
456
Q_D(QQuickTreeViewDelegate);
457
if
(d->m_editing == editing)
458
return
;
459
460
d->m_editing = editing;
461
emit editingChanged();
462
}
463
464
int
QQuickTreeViewDelegate::depth()
const
465
{
466
return
d_func()->m_depth;
467
}
468
469
void
QQuickTreeViewDelegate::setDepth(
int
depth)
470
{
471
Q_D(QQuickTreeViewDelegate);
472
if
(d->m_depth == depth)
473
return
;
474
475
d->m_depth = depth;
476
emit depthChanged();
477
}
478
479
QQuickTreeView *QQuickTreeViewDelegate::treeView()
const
480
{
481
return
d_func()->m_treeView;
482
}
483
484
void
QQuickTreeViewDelegate::setTreeView(QQuickTreeView *treeView)
485
{
486
Q_D(QQuickTreeViewDelegate);
487
if
(d->m_treeView == treeView)
488
return
;
489
490
d->m_treeView = treeView;
491
emit treeviewChanged();
492
}
493
494
void
QQuickTreeViewDelegate::componentComplete()
495
{
496
Q_D(QQuickTreeViewDelegate);
497
QQuickItemDelegate::componentComplete();
498
d->updateIndicatorVisibility();
499
d->updateIndicatorPointerHandlers();
500
}
501
502
qreal QQuickTreeViewDelegate::leftMargin()
const
503
{
504
return
d_func()->m_leftMargin;
505
}
506
507
void
QQuickTreeViewDelegate::setLeftMargin(qreal leftMargin)
508
{
509
Q_D(QQuickTreeViewDelegate);
510
if
(qFuzzyCompare(d->m_leftMargin, leftMargin))
511
return
;
512
513
d->m_leftMargin = leftMargin;
514
emit leftMarginChanged();
515
}
516
517
qreal QQuickTreeViewDelegate::rightMargin()
const
518
{
519
return
d_func()->m_rightMargin;
520
}
521
522
void
QQuickTreeViewDelegate::setRightMargin(qreal rightMargin)
523
{
524
Q_D(QQuickTreeViewDelegate);
525
if
(qFuzzyCompare(d->m_rightMargin, rightMargin))
526
return
;
527
528
d->m_rightMargin = rightMargin;
529
emit rightMarginChanged();
530
}
531
532
QT_END_NAMESPACE
533
534
#
include
"moc_qquicktreeviewdelegate_p.cpp"
QQuickTreeViewDelegatePrivate
Definition
qquicktreeviewdelegate.cpp:223
QQuickTreeViewDelegatePrivate::m_rightMargin
qreal m_rightMargin
Definition
qquicktreeviewdelegate.cpp:237
QQuickTreeViewDelegatePrivate::m_pressOnTopOfIndicator
bool m_pressOnTopOfIndicator
Definition
qquicktreeviewdelegate.cpp:244
QQuickTreeViewDelegatePrivate::updateIndicatorPointerHandlers
void updateIndicatorPointerHandlers()
Definition
qquicktreeviewdelegate.cpp:262
QQuickTreeViewDelegatePrivate::m_editing
bool m_editing
Definition
qquicktreeviewdelegate.cpp:242
QQuickTreeViewDelegatePrivate::m_expanded
bool m_expanded
Definition
qquicktreeviewdelegate.cpp:239
QQuickTreeViewDelegatePrivate::toggleExpanded
void toggleExpanded()
Definition
qquicktreeviewdelegate.cpp:248
QQuickTreeViewDelegatePrivate::m_current
bool m_current
Definition
qquicktreeviewdelegate.cpp:240
QQuickTreeViewDelegatePrivate::m_selected
bool m_selected
Definition
qquicktreeviewdelegate.cpp:241
QQuickTreeViewDelegatePrivate::m_isTreeNode
bool m_isTreeNode
Definition
qquicktreeviewdelegate.cpp:238
QQuickTreeViewDelegatePrivate::m_treeView
QPointer< QQuickTreeView > m_treeView
Definition
qquicktreeviewdelegate.cpp:233
QQuickTreeViewDelegatePrivate::m_indentation
qreal m_indentation
Definition
qquicktreeviewdelegate.cpp:235
QQuickTreeViewDelegatePrivate::m_tapHandlerOnIndicator
QPointer< QQuickTapHandler > m_tapHandlerOnIndicator
Definition
qquicktreeviewdelegate.cpp:234
QQuickTreeViewDelegatePrivate::updateIndicatorVisibility
void updateIndicatorVisibility()
Definition
qquicktreeviewdelegate.cpp:281
QQuickTreeViewDelegatePrivate::m_depth
int m_depth
Definition
qquicktreeviewdelegate.cpp:245
QQuickTreeViewDelegatePrivate::defaultPalette
QPalette defaultPalette() const override
Definition
qquicktreeviewdelegate.cpp:347
QQuickTreeViewDelegatePrivate::m_leftMargin
qreal m_leftMargin
Definition
qquicktreeviewdelegate.cpp:236
QQuickTreeViewDelegatePrivate::m_hasChildren
bool m_hasChildren
Definition
qquicktreeviewdelegate.cpp:243
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
qtdeclarative
src
quicktemplates
qquicktreeviewdelegate.cpp
Generated on
for Qt by
1.18.0