Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qquickpointerhandler.cpp
Go to the documentation of this file.
1// Copyright (C) 2018 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
6#include <QtQuick/private/qquickitem_p.h>
7#include <QtQuick/private/qquickhandlerpoint_p.h>
8#include <QtQuick/private/qquickdeliveryagent_p_p.h>
9#include <QtGui/private/qinputdevice_p.h>
10
11#include <QtCore/qpointer.h>
12
14
15Q_LOGGING_CATEGORY(lcPointerHandlerDispatch, "qt.quick.handler.dispatch")
16Q_LOGGING_CATEGORY(lcPointerHandlerGrab, "qt.quick.handler.grab")
17Q_LOGGING_CATEGORY(lcPointerHandlerActive, "qt.quick.handler.active")
18Q_DECLARE_LOGGING_CATEGORY(lcHandlerParent)
19
49
51 : QObject(dd, parent)
52{
53 // When a handler is created in QML, the given parent is null, and we
54 // depend on QQuickItemPrivate::data_append() later when it's added to an
55 // item's DefaultProperty data property. But when a handler is created in
56 // C++ with a parent item, data_append() won't be called, and the caller
57 // shouldn't have to worry about it either.
58 if (parent)
59 QQuickItemPrivate::get(parent)->addPointerHandler(this);
60}
61
63{
64 QQuickItem *parItem = parentItem();
65 if (parItem) {
67 p->extra.value().pointerHandlers.removeOne(this);
68 }
69}
70
89{
90 Q_D(const QQuickPointerHandler);
91 return d->m_margin;
92}
93
94void QQuickPointerHandler::setMargin(qreal pointDistanceThreshold)
95{
97 if (d->m_margin == pointDistanceThreshold)
98 return;
99
100 d->m_margin = pointDistanceThreshold;
102}
103
116{
117 Q_D(const QQuickPointerHandler);
118 if (d->dragThreshold < 0)
119 return qApp->styleHints()->startDragDistance();
120 return d->dragThreshold;
121}
122
124{
126 if (d->dragThreshold == t)
127 return;
128
129 if (t > std::numeric_limits<qint16>::max())
130 qWarning() << "drag threshold cannot exceed" << std::numeric_limits<qint16>::max();
131 d->dragThreshold = qint16(t);
132 emit dragThresholdChanged();
133}
134
136{
138 if (d->dragThreshold < 0)
139 return;
140
141 d->dragThreshold = -1;
142 emit dragThresholdChanged();
143}
144
186#if QT_CONFIG(cursor)
187Qt::CursorShape QQuickPointerHandler::cursorShape() const
188{
189 Q_D(const QQuickPointerHandler);
190 return d->cursorShape;
191}
192
193void QQuickPointerHandler::setCursorShape(Qt::CursorShape shape)
194{
196 if (d->cursorSet && shape == d->cursorShape)
197 return;
198 d->cursorShape = shape;
199 d->cursorSet = true;
200 d->cursorDirty = true;
201 if (auto *parent = parentItem()) {
203 itemPriv->hasCursorHandler = true;
204 itemPriv->setHasCursorInChild(true);
205 }
206
207 emit cursorShapeChanged();
208}
209
210void QQuickPointerHandler::resetCursorShape()
211{
213 if (!d->cursorSet)
214 return;
215 d->cursorShape = Qt::ArrowCursor;
216 d->cursorSet = false;
217 if (auto *parent = parentItem()) {
219 itemPriv->hasCursorHandler = false;
220 itemPriv->setHasCursorInChild(itemPriv->hasCursor);
221 }
222 emit cursorShapeChanged();
223}
224
225bool QQuickPointerHandler::isCursorShapeExplicitlySet() const
226{
227 Q_D(const QQuickPointerHandler);
228 return d->cursorSet;
229}
230#endif
231
247{
249 qCDebug(lcPointerHandlerGrab) << point << transition << grabber;
250 if (grabber == this) {
251 bool wasCanceled = false;
252 switch (transition) {
255 break;
258 wasCanceled = true; // the grab was stolen by something else
262 setActive(false);
263 point.setAccepted(false);
264 if (auto par = parentItem()) {
265 Q_D(const QQuickPointerHandler);
266 par->setKeepMouseGrab(d->hadKeepMouseGrab);
267 par->setKeepTouchGrab(d->hadKeepTouchGrab);
268 }
269 break;
271 // Passive grab is still there, but we won't receive point updates right now.
272 // No need to notify about this.
273 return;
274 }
275 if (wasCanceled)
276 emit canceled(point);
277 emit grabChanged(transition, point);
278 }
279}
280
297{
298 qCDebug(lcPointerHandlerGrab) << this << point << grab << "via"
300 if (grab) {
301 event->addPassiveGrabber(point, this);
302 } else {
303 event->removePassiveGrabber(point, this);
304 }
305}
306
319{
320 QQuickPointerHandler *existingPhGrabber = qobject_cast<QQuickPointerHandler *>(event->exclusiveGrabber(point));
321 return approveGrabTransition(event, point, this) &&
322 (existingPhGrabber ? existingPhGrabber->approveGrabTransition(event, point, this) : true);
323}
324
332{
333 Q_D(const QQuickPointerHandler);
334 bool allowed = false;
335 QObject* existingGrabber = event->exclusiveGrabber(point);
336 if (proposedGrabber == this) {
337 allowed = (existingGrabber == nullptr) || ((d->grabPermissions & CanTakeOverFromAnything) == CanTakeOverFromAnything);
338 if (existingGrabber) {
339 if (QQuickPointerHandler *existingPhGrabber = qobject_cast<QQuickPointerHandler *>(event->exclusiveGrabber(point))) {
340 if (!allowed && (d->grabPermissions & CanTakeOverFromHandlersOfDifferentType) &&
341 existingPhGrabber->metaObject()->className() != metaObject()->className())
342 allowed = true;
343 if (!allowed && (d->grabPermissions & CanTakeOverFromHandlersOfSameType) &&
344 existingPhGrabber->metaObject()->className() == metaObject()->className())
345 allowed = true;
346 } else if ((d->grabPermissions & CanTakeOverFromItems)) {
347 allowed = true;
348 QQuickItem * existingItemGrabber = qobject_cast<QQuickItem *>(event->exclusiveGrabber(point));
349 auto da = parentItem() ? QQuickItemPrivate::get(parentItem())->deliveryAgentPrivate()
352 const bool isTouchMouse = (da && da->isDeliveringTouchAsMouse());
353 if (existingItemGrabber &&
354 ((existingItemGrabber->keepMouseGrab() &&
356 (existingItemGrabber->keepTouchGrab() && QQuickDeliveryAgentPrivate::isTouchEvent(event)))) {
357 allowed = false;
358 // If the handler wants to steal the exclusive grab from an Item, the Item can usually veto
359 // by having its keepMouseGrab flag set. But an exception is if that Item is a parent that
360 // normally filters events (such as a Flickable): it needs to be possible for e.g. a
361 // DragHandler to operate on an Item inside a Flickable. Flickable is aggressive about
362 // grabbing on press (for fear of missing updates), but DragHandler uses a passive grab
363 // at first and then expects to be able to steal the grab later on. It cannot respect
364 // Flickable's wishes in that case, because then it would never have a chance.
365 if (existingItemGrabber->keepMouseGrab() &&
366 existingItemGrabber->filtersChildMouseEvents() && existingItemGrabber->isAncestorOf(parentItem())) {
367 Q_ASSERT(da);
368 if (isTouchMouse && point.id() == da->touchMouseId) {
369 qCDebug(lcPointerHandlerGrab) << this << "steals touchpoint" << point.id()
370 << "despite parent touch-mouse grabber with keepMouseGrab=true" << existingItemGrabber;
371 allowed = true;
372 }
373 }
374 if (!allowed) {
375 qCDebug(lcPointerHandlerGrab) << this << "wants to grab point" << point.id()
376 << "but declines to steal from grabber" << existingItemGrabber
377 << "with keepMouseGrab=" << existingItemGrabber->keepMouseGrab()
378 << "keepTouchGrab=" << existingItemGrabber->keepTouchGrab();
379 }
380 }
381 }
382 }
383 } else {
384 // proposedGrabber is different: that means this instance will lose its grab
385 if (proposedGrabber) {
386 if ((d->grabPermissions & ApprovesTakeOverByAnything) == ApprovesTakeOverByAnything)
387 allowed = true;
388 if (!allowed && (d->grabPermissions & ApprovesTakeOverByHandlersOfDifferentType) &&
389 proposedGrabber->metaObject()->className() != metaObject()->className())
390 allowed = true;
391 if (!allowed && (d->grabPermissions & ApprovesTakeOverByHandlersOfSameType) &&
392 proposedGrabber->metaObject()->className() == metaObject()->className())
393 allowed = true;
394 if (!allowed && (d->grabPermissions & ApprovesTakeOverByItems) && proposedGrabber->inherits("QQuickItem"))
395 allowed = true;
396 } else {
397 if (d->grabPermissions & ApprovesCancellation)
398 allowed = true;
399 }
400 }
401 qCDebug(lcPointerHandlerGrab) << "point" << Qt::hex << point.id() << "permission" <<
402 QMetaEnum::fromType<GrabPermissions>().valueToKeys(grabPermissions()) <<
403 ':' << this << (allowed ? "approved from" : "denied from") <<
404 existingGrabber << "to" << proposedGrabber;
405 return allowed;
406}
407
441QQuickPointerHandler::GrabPermissions QQuickPointerHandler::grabPermissions() const
442{
443 Q_D(const QQuickPointerHandler);
444 return static_cast<QQuickPointerHandler::GrabPermissions>(d->grabPermissions);
445}
446
447void QQuickPointerHandler::setGrabPermissions(GrabPermissions grabPermission)
448{
450 if (d->grabPermissions == grabPermission)
451 return;
452
453 d->grabPermissions = grabPermission;
455}
456
463
469{
470 Q_D(const QQuickPointerHandler);
471 if (d->cursorSet) {
472 if (auto *parent = parentItem()) {
474 itemPriv->hasCursorHandler = true;
475 itemPriv->setHasCursorInChild(true);
476 }
477 }
478}
479
487{
488 Q_D(const QQuickPointerHandler);
489 return d->currentEvent;
490}
491
501{
502 if ((grab && ev->exclusiveGrabber(point) == this) || (!grab && ev->exclusiveGrabber(point) != this))
503 return true;
504 // TODO m_hadKeepMouseGrab m_hadKeepTouchGrab
505 bool allowed = true;
506 if (grab) {
507 allowed = canGrab(ev, point);
508 } else {
509 QQuickPointerHandler *existingPhGrabber = qobject_cast<QQuickPointerHandler *>(ev->exclusiveGrabber(point));
510 // Ask before allowing one handler to cancel another's grab
511 if (existingPhGrabber && existingPhGrabber != this && !existingPhGrabber->approveGrabTransition(ev, point, nullptr))
512 allowed = false;
513 }
514 qCDebug(lcPointerHandlerGrab) << point << (grab ? "grab" : "ungrab") << (allowed ? "allowed" : "forbidden") <<
515 ev->exclusiveGrabber(point) << "->" << (grab ? this : nullptr);
516 if (allowed)
517 ev->setExclusiveGrabber(point, grab ? this : nullptr);
518 return allowed;
519}
520
525{
526 qCDebug(lcPointerHandlerGrab) << point;
527 if (event->exclusiveGrabber(point) == this) {
528 event->setExclusiveGrabber(point, nullptr);
530 }
531 if (event->removePassiveGrabber(point, this))
533}
534
536{
537 return (target() ? target()->mapFromScene(point.scenePosition()) : point.scenePosition());
538}
539
547{
548 return parentContains(point.scenePosition());
549}
550
559bool QQuickPointerHandler::parentContains(const QPointF &scenePosition) const
560{
561 if (QQuickItem *par = parentItem()) {
562 if (par->window()) {
563 QRectF windowGeometry = par->window()->geometry();
564 if (!par->window()->isTopLevel())
565 windowGeometry = QRectF(QWindowPrivate::get(par->window())->globalPosition(), par->window()->size());
566 QPointF screenPosition = par->window()->mapToGlobal(scenePosition);
567 if (!windowGeometry.contains(screenPosition))
568 return false;
569 }
570 QPointF p = par->mapFromScene(scenePosition);
571 qreal m = margin();
572 if (m > 0)
573 return p.x() >= -m && p.y() >= -m && p.x() <= par->width() + m && p.y() <= par->height() + m;
574 return par->contains(p);
575 } else if (parent() && parent()->inherits("QQuick3DModel")) {
576 // If the parent is from Qt Quick 3D, assume that
577 // bounds checking was already done, as part of picking.
578 return true;
579 }
580 return false;
581}
582
590{
591 Q_D(const QQuickPointerHandler);
592 return d->enabled;
593}
594
596{
598 if (d->enabled == enabled)
599 return;
600
601 d->enabled = enabled;
602 d->onEnabledChanged();
603
605}
606
619{
620 Q_D(const QQuickPointerHandler);
621 if (!d->targetExplicitlySet)
622 return parentItem();
623 return d->target;
624}
625
627{
629 d->targetExplicitlySet = true;
630 if (d->target == target)
631 return;
632
633 QQuickItem *oldTarget = d->target;
634 d->target = target;
635 onTargetChanged(oldTarget);
637}
638
664
666{
668 if (QObject::parent() == p)
669 return;
670
671 qCDebug(lcHandlerParent) << "reparenting handler" << this << ":" << parent() << "->" << p;
672 auto *oldParent = static_cast<QQuickItem *>(QObject::parent());
673 if (oldParent)
674 QQuickItemPrivate::get(oldParent)->removePointerHandler(this);
675 setParent(p);
676 if (p)
677 QQuickItemPrivate::get(p)->addPointerHandler(this);
678 d->onParentChanged(oldParent, p);
679 emit parentChanged();
680}
681
689{
690 switch (e->type()) {
691 case QEvent::TouchCancel: {
692 auto te = static_cast<QTouchEvent *>(e);
693 for (int i = 0; i < te->pointCount(); ++i)
695 return true;
696 break;
697 }
698 default:
699 return QObject::event(e);
700 break;
701 }
702}
703
710{
712 bool wants = wantsPointerEvent(event);
713 qCDebug(lcPointerHandlerDispatch) << metaObject()->className() << objectName()
714 << "on" << parent()->metaObject()->className() << parent()->objectName()
715 << (wants ? "WANTS" : "DECLINES") << event;
716 d->currentEvent = event;
717 if (wants) {
719 d->lastEventTime = event->timestamp();
720 } else {
721#if QT_CONFIG(gestures)
722 if (event->type() != QEvent::NativeGesture)
723#endif
724 setActive(false);
725 for (int i = 0; i < event->pointCount(); ++i) {
726 auto &pt = event->point(i);
727 if (event->exclusiveGrabber(pt) == this && pt.state() != QEventPoint::Stationary)
728 event->setExclusiveGrabber(pt, nullptr);
729 }
730 }
731 d->currentEvent = nullptr;
733}
734
758{
759 Q_D(const QQuickPointerHandler);
761 return d->enabled;
762}
763
786{
788 bool ret = event->exclusiveGrabber(point) == this ||
789 event->passiveGrabbers(point).contains(this) || parentContains(point);
790 qCDebug(lcPointerHandlerDispatch) << Qt::hex << point.id() << "@" << point.scenePosition()
791 << metaObject()->className() << objectName() << ret;
792 return ret;
793}
794
806{
807 Q_D(const QQuickPointerHandler);
808 return d->active;
809}
810
812{
814 if (d->active != active) {
815 qCDebug(lcPointerHandlerActive) << this << d->active << "->" << active;
816 d->active = active;
819 }
820}
821
838
872 : grabPermissions(QQuickPointerHandler::CanTakeOverFromItems |
873 QQuickPointerHandler::CanTakeOverFromHandlersOfDifferentType |
874 QQuickPointerHandler::ApprovesTakeOverByAnything)
875 , cursorShape(Qt::ArrowCursor)
876 , enabled(true)
877 , active(false)
878 , targetExplicitlySet(false)
879 , hadKeepMouseGrab(false)
880 , hadKeepTouchGrab(false)
881 , cursorSet(false)
882 , cursorDirty(false)
883{
884}
885
893template <typename TEventPoint>
895{
896 Q_Q(const QQuickPointerHandler);
897 QStyleHints *styleHints = qApp->styleHints();
898 bool overThreshold = qAbs(d) > q->dragThreshold();
899 const bool dragVelocityLimitAvailable = (styleHints->startDragVelocity() > 0);
900 if (!overThreshold && dragVelocityLimitAvailable) {
901 qreal velocity = qreal(axis == Qt::XAxis ? p.velocity().x() : p.velocity().y());
902 overThreshold |= qAbs(velocity) > styleHints->startDragVelocity();
903 }
904 return overThreshold;
905}
906
914{
915 Q_Q(const QQuickPointerHandler);
916 const float threshold = q->dragThreshold();
917 return qAbs(delta.x()) > threshold || qAbs(delta.y()) > threshold;
918}
919
928{
929 QPointF delta = point.scenePosition() - point.scenePressPosition();
930 return (dragOverThreshold(delta.x(), Qt::XAxis, point) ||
931 dragOverThreshold(delta.y(), Qt::YAxis, point));
932}
933
938
940
941#include "moc_qquickpointerhandler_p.cpp"
IOBluetoothDevice * device
The QEventPoint class provides information about a point in a QPointerEvent.
Definition qeventpoint.h:20
int id
the ID number of this event point.
Definition qeventpoint.h:24
QPointF scenePosition
the scene position of this point.
Definition qeventpoint.h:39
void setAccepted(bool accepted=true)
QPointF scenePressPosition
the scene position at which this point was pressed.
Definition qeventpoint.h:40
\inmodule QtCore
Definition qcoreevent.h:45
@ NativeGesture
Definition qcoreevent.h:246
@ TouchCancel
Definition qcoreevent.h:264
Type type() const
Returns the event type.
Definition qcoreevent.h:304
The QInputDevice class describes a device from which a QInputEvent originates.
static QObjectPrivate * get(QObject *o)
Definition qobject_p.h:150
\inmodule QtCore
Definition qobject.h:103
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
QString objectName
the name of this object
Definition qobject.h:107
virtual bool event(QEvent *event)
This virtual function receives events to an object and should return true if the event e was recogniz...
Definition qobject.cpp:1389
void setParent(QObject *parent)
Makes the object a child of parent.
Definition qobject.cpp:2195
bool inherits(const char *classname) const
Returns true if this object is an instance of a class that inherits className or a QObject subclass t...
Definition qobject.h:348
\inmodule QtCore\reentrant
Definition qpoint.h:217
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:343
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:348
A base class for pointer events.
Definition qevent.h:73
GrabTransition
This enum represents a transition of exclusive or passive grab from one object (possibly nullptr) to ...
static QQuickPointingDeviceExtra * deviceExtra(const QInputDevice *device)
static QQuickDeliveryAgent * currentEventDeliveryAgent
static bool isTouchEvent(const QPointerEvent *ev)
static bool isMouseEvent(const QPointerEvent *ev)
static QQuickDeliveryAgent * currentOrItemDeliveryAgent(const QQuickItem *item)
static QQuickItemPrivate * get(QQuickItem *item)
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:63
QQuickPointerHandlerPrivate()
\qmlsignal QtQuick::PointerHandler::grabChanged(PointerDevice::GrabTransition transition,...
static QVector< QObject * > & deviceDeliveryTargets(const QInputDevice *device)
bool dragOverThreshold(qreal d, Qt::Axis axis, const TEventPoint &p) const
virtual bool canGrab(QPointerEvent *event, const QEventPoint &point)
Check whether it's OK to take an exclusive grab of the point.
bool parentContains(const QEventPoint &point) const
Returns true if margin() > 0 and point is within the margin beyond QQuickItem::boundingRect(),...
QQuickItem * parentItem() const
\qmlproperty Item QtQuick::PointerHandler::parent
void handlePointerEvent(QPointerEvent *event)
QQuickPointerHandler(QQuickItem *parent=nullptr)
\qmltype PointerHandler \qmlabstract
void grabChanged(QPointingDevice::GrabTransition transition, QEventPoint point)
void cancelAllGrabs(QPointerEvent *event, QEventPoint &point)
Cancel any existing grab of the given point.
virtual bool wantsPointerEvent(QPointerEvent *event)
It is the responsibility of this function to decide whether the event could be relevant at all to thi...
void setMargin(qreal pointDistanceThreshold)
virtual bool approveGrabTransition(QPointerEvent *event, const QEventPoint &point, QObject *proposedGrabber)
Check this handler's rules to see if \l proposedGrabber will be allowed to take the exclusive grab.
virtual bool wantsEventPoint(const QPointerEvent *event, const QEventPoint &point)
Returns true if the given point (as part of event) could be relevant at all to this handler,...
void setPassiveGrab(QPointerEvent *event, const QEventPoint &point, bool grab=true)
Acquire or give up a passive grab of the given point, according to the grab state.
void setGrabPermissions(GrabPermissions grabPermissions)
virtual void onGrabChanged(QQuickPointerHandler *grabber, QPointingDevice::GrabTransition transition, QPointerEvent *event, QEventPoint &point)
Notification that the grab has changed in some way which is relevant to this handler.
void setParentItem(QQuickItem *p)
void componentComplete() override
Overridden from QQmlParserStatus to ensure that parentItem() sets its cursor if this handler's \l cur...
virtual void onTargetChanged(QQuickItem *oldTarget)
QPointF eventPos(const QEventPoint &point) const
virtual void handlePointerEventImpl(QPointerEvent *event)
This function can be overridden to implement whatever behavior a specific subclass is intended to hav...
void setEnabled(bool enabled)
void classBegin() override
Overridden only because QQmlParserStatus requires it.
void setTarget(QQuickItem *target)
bool setExclusiveGrab(QPointerEvent *ev, const QEventPoint &point, bool grab=true)
Acquire or give up the exclusive grab of the given point, according to the grab state,...
void canceled(QEventPoint point)
bool event(QEvent *) override
\inmodule QtCore\reentrant
Definition qrect.h:484
bool contains(const QRectF &r) const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qrect.cpp:1993
The QStyleHints class contains platform specific hints and settings. \inmodule QtGui.
Definition qstylehints.h:17
int startDragVelocity
the limit for the velocity, in pixels per second, that the mouse may be moved, with a button held dow...
Definition qstylehints.h:43
The QTouchEvent class contains parameters that describe a touch event.
Definition qevent.h:917
The QVector2D class represents a vector or vertex in 2D space.
Definition qvectornd.h:31
constexpr float y() const noexcept
Returns the y coordinate of this point.
Definition qvectornd.h:502
constexpr float x() const noexcept
Returns the x coordinate of this point.
Definition qvectornd.h:501
static QWindowPrivate * get(QWindow *window)
Definition qwindow_p.h:106
#define this
Definition dialogs.cpp:9
Combined button and popup list for selecting options.
Definition qcompare.h:63
QTextStream & hex(QTextStream &stream)
Calls QTextStream::setIntegerBase(16) on stream and returns stream.
CursorShape
@ ArrowCursor
@ XAxis
@ YAxis
#define Q_FALLTHROUGH()
#define qApp
#define qWarning
Definition qlogging.h:166
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
return ret
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
const GLfloat * m
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLenum target
struct _cl_event * event
GLdouble GLdouble t
Definition qopenglext.h:243
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLfloat GLfloat p
[1]
QQuickItem * qmlobject_cast< QQuickItem * >(QObject *object)
QQuickItem * qobject_cast< QQuickItem * >(QObject *o)
Definition qquickitem.h:492
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define emit
#define Q_UNUSED(x)
short qint16
Definition qtypes.h:47
double qreal
Definition qtypes.h:187
const char className[16]
[1]
Definition qwizard.cpp:100
obj metaObject() -> className()