QSkinny 0.8.0
C++/Qt UI toolkit
Loading...
Searching...
No Matches
QskItem.cpp
1/******************************************************************************
2 * QSkinny - Copyright (C) The authors
3 * SPDX-License-Identifier: BSD-3-Clause
4 *****************************************************************************/
5
6#include "QskItem.h"
7#include "QskItemPrivate.h"
8#include "QskQuick.h"
9#include "QskEvent.h"
10#include "QskSetup.h"
11#include "QskSkinManager.h"
12#include "QskSkin.h"
13#include "QskDirtyItemFilter.h"
14
15#include <qglobalstatic.h>
16#include <qquickwindow.h>
17
18#if defined( QT_DEBUG )
19
20QSK_QT_PRIVATE_BEGIN
21
22#if QT_VERSION >= QT_VERSION_CHECK( 6, 2, 0 )
23 #ifndef emit
24 #define emit
25 #include <private/qabstractanimation_p.h>
26 #undef emit
27 #endif
28#endif
29
30#if defined( QT_DEBUG )
31#include <private/qquickpositioners_p.h>
32#endif
33
34#include <private/qquickitemchangelistener_p.h>
35
36QSK_QT_PRIVATE_END
37
38#endif
39
40#include <unordered_set>
41
42static inline void qskSendEventTo( QObject* object, QEvent::Type type )
43{
44 QEvent event( type );
45 QCoreApplication::sendEvent( object, &event );
46}
47
48static inline void qskApplyUpdateFlags(
49 QskItem::UpdateFlags flags, QskItem* item )
50{
51 auto d = static_cast< QskItemPrivate* >( QskItemPrivate::get( item ) );
52 d->applyUpdateFlags( flags );
53}
54
55static inline void qskFilterWindow( QQuickWindow* window )
56{
57 if ( window == nullptr )
58 return;
59
60 static QskDirtyItemFilter itemFilter;
61 itemFilter.addWindow( window );
62}
63
64namespace
65{
66 class QskItemRegistry
67 {
68 public:
69 QskItemRegistry()
70 {
71 /*
72 Its faster and saves some memory to have this registry instead
73 of setting up direct connections between qskSetup and each control
74
75 We would also need to send QEvent::StyleChange, when
76 a window has a new skin. TODO ...
77 */
78 QObject::connect( qskSkinManager, &QskSkinManager::skinChanged,
79 qskSkinManager, [ this ] { updateSkin(); } );
80
81 QObject::connect( qskSkinManager, &QskSkinManager::colorSchemeChanged,
82 qskSkinManager, [ this ] { updateSkin(); } );
83 }
84
85 inline void insert( QskItem* item )
86 {
87 m_items.insert( item );
88 }
89
90 inline void remove( QskItem* item )
91 {
92 m_items.erase( item );
93 }
94
95 void updateItemFlags()
96 {
97 const auto flags = QskSetup::updateFlags();
98
99 for ( auto item : m_items )
100 qskApplyUpdateFlags( flags, item );
101 }
102
103 void updateSkin()
104 {
105 QEvent event( QEvent::StyleChange );
106
107 for ( auto item : m_items )
108 {
109 event.setAccepted( true );
110 QCoreApplication::sendEvent( item, &event );
111 }
112 }
113
114 private:
115 std::unordered_set< QskItem* > m_items;
116 };
117}
118
119namespace
120{
121 /*
122 A helper class to store the released window to be able to
123 put it later into the WindowChange event.
124 */
125 class QskWindowStore
126 {
127 public:
128 QskWindowStore()
129 : m_refCount( 0 )
130 , m_window( nullptr )
131 {
132 }
133
134 void setWindow( QQuickWindow* window )
135 {
136 if ( m_window != window )
137 {
138 m_window = window;
139 m_refCount = 0;
140 }
141
142 if ( m_window )
143 m_refCount++;
144 }
145
146 QQuickWindow* window()
147 {
148 QQuickWindow* w = m_window;
149
150 if ( m_window )
151 {
152 if ( --m_refCount == 0 )
153 m_window = nullptr;
154 }
155
156 return w;
157 }
158
159 private:
160 int m_refCount;
161 QQuickWindow* m_window;
162 };
163}
164
165namespace
166{
167 // A helper class for the polishOnParentResize feature
168
169 class QskParentListener final : public QQuickItemChangeListener
170 {
171 public:
172 void update( QQuickItem* parentItem )
173 {
174 if ( parentItem == nullptr )
175 return;
176
177 const auto changeTypes =
178 QQuickItemPrivate::Geometry | QQuickItemPrivate::Children;
179
180 auto d = QQuickItemPrivate::get( parentItem );
181
182 if ( needListening( parentItem ) )
183 d->updateOrAddItemChangeListener( this, changeTypes );
184 else
185 d->removeItemChangeListener( this, changeTypes );
186 }
187
188 private:
189 inline bool needListening( const QQuickItem* parentItem ) const
190 {
191 const auto children = parentItem->childItems();
192 for ( auto child : children )
193 {
194 if ( auto item = qobject_cast< const QskItem* >( child ) )
195 {
196 if ( item->polishOnParentResize() )
197 return true;
198 }
199 }
200
201 return false;
202 }
203
204 void itemGeometryChanged( QQuickItem* parentItem,
205 QQuickGeometryChange, const QRectF& ) override
206 {
207 const auto children = parentItem->childItems();
208 for ( auto child : children )
209 {
210 if ( auto item = qobject_cast< QskItem* >( child ) )
211 {
212 if ( item->polishOnParentResize() )
213 {
214 item->resetImplicitSize();
215 item->polish();
216 }
217 }
218 }
219 }
220
221 void itemChildRemoved( QQuickItem* parentItem, QQuickItem* )
222 {
223 update( parentItem );
224 }
225 };
226}
227
228Q_GLOBAL_STATIC( QskItemRegistry, qskRegistry )
229Q_GLOBAL_STATIC( QskWindowStore, qskReleasedWindowCounter )
230Q_GLOBAL_STATIC( QskParentListener, qskParentListener )
231
232QskItem::QskItem( QskItemPrivate& dd, QQuickItem* parent )
233 : QQuickItem( dd, parent )
234{
235 setFlag( QQuickItem::ItemHasContents, true );
236 Inherited::setActiveFocusOnTab( false );
237
238 if ( dd.updateFlags & QskItem::DeferredUpdate )
239 qskFilterWindow( window() );
240
241 qskRegistry->insert( this );
242}
243
244QskItem::~QskItem()
245{
246 /*
247 We set componentComplete to false, so that operations
248 that are triggered by detaching the item from its parent
249 can be aware of the about-to-delete state.
250
251 Note, that since Qt >= 6.5 this information is stored
252 in QQuickItemPrivate::inDestructor.
253
254 s.a: qskIsItemInDestructor
255 */
256 d_func()->componentComplete = false;
257
258 if ( qskRegistry )
259 qskRegistry->remove( this );
260}
261
262const char* QskItem::className() const
263{
264 return metaObject()->className();
265}
266
268{
269 Inherited::classBegin();
270}
271
273{
274#if defined( QT_DEBUG )
275 if ( d_func()->updateFlags & QskItem::DeferredLayout )
276 {
277 if ( qobject_cast< const QQuickBasePositioner* >( parent() ) )
278 {
279 qWarning( "QskItem in DeferredLayout mode under control of a positioner" );
280 }
281 }
282#endif
283
284 Inherited::componentComplete();
285}
286
288{
289 Inherited::releaseResources();
290
291 // QQuickItem::derefWindow runs over the children between
292 // calling releaseResources and itemChange. So we need to have
293 // a reference count to know, when we have processed all
294 // sequences to be able to provide the correct "oldWindow"
295 // in the WindowChange event.
296
297 qskReleasedWindowCounter->setWindow( window() );
298}
299
300void QskItem::setDisabled( bool on )
301{
302 Inherited::setEnabled( !on );
303}
304
305void QskItem::setHidden( bool on )
306{
307 Inherited::setVisible( !on );
308}
309
311{
312 Inherited::setVisible( true );
313}
314
316{
317 Inherited::setVisible( false );
318}
319
320bool QskItem::isVisibleTo( const QQuickItem* ancestor ) const
321{
322 return qskIsVisibleTo( this, ancestor );
323}
324
326{
327 return d_func()->explicitVisible;
328}
329
330void QskItem::setGeometry( qreal x, qreal y, qreal width, qreal height )
331{
332 // QQuickItem does not even offer changing the geometry
333 // in one call - what leads to 2 calls of the updateGeometry
334 // hook. Grmpf ...
335
336 Q_D( QQuickItem );
337
338#if QT_VERSION >= QT_VERSION_CHECK( 6, 2, 0 )
339 d->heightValidFlag = true;
340 d->widthValidFlag = true;
341#else
342 d->heightValid = true;
343 d->widthValid = true;
344#endif
345
346 const QRectF oldRect( d->x, d->y, d->width, d->height );
347
348 int dirtyType = 0;
349
350 if ( d->x != x || d->y != y )
351 {
352 d->x = x;
353 d->y = y;
354
355 dirtyType |= QQuickItemPrivate::Position;
356 }
357
358 if ( d->width != width || d->height != height )
359 {
360 d->height = height;
361 d->width = width;
362
363 dirtyType |= QQuickItemPrivate::Size;
364 }
365
366 if ( dirtyType )
367 {
368 if ( dirtyType & QQuickItemPrivate::Position )
369 d->dirty( QQuickItemPrivate::Position );
370
371 if ( dirtyType & QQuickItemPrivate::Size )
372 d->dirty( QQuickItemPrivate::Size );
373
374 /*
375 Unfortunately geometryChange(d) is protected and we can't implement
376 this code as qskSetItemGeometry - further hacking required: TODO ...
377 */
378
379 const QRectF newRect( d->x, d->y, d->width, d->height );
380#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
381 geometryChange( newRect, oldRect );
382#else
383 geometryChanged( newRect, oldRect );
384#endif
385 }
386}
387
388QRectF QskItem::rect() const
389{
390 Q_D( const QQuickItem );
391 return QRectF( 0, 0, d->width, d->height );
392}
393
394QRectF QskItem::geometry() const
395{
396 Q_D( const QQuickItem );
397 return QRectF( d->x, d->y, d->width, d->height );
398}
399
400void QskItem::setTabFence( bool on )
401{
402 Q_D( QQuickItem );
403 if ( on != d->isTabFence )
404 {
405 d->isTabFence = on;
406 Q_EMIT itemFlagsChanged();
407 }
408}
409
411{
412 return d_func()->isTabFence;
413}
414
415void QskItem::setFocusPolicy( Qt::FocusPolicy policy )
416{
417 /*
418 Qt::FocusPolicy has always been there with widgets, got lost with
419 Qt/Quick and has been reintroduced with Qt/Quick Controls 2 ( QC2 ).
420 Unfortunately this was done by adding code on top instead of fixing
421 the foundation.
422 */
423 Q_D( QskItem );
424 if ( policy != d->focusPolicy )
425 {
426 d->focusPolicy = ( policy & ~Qt::TabFocus );
427
428 const bool tabFocus = policy & Qt::TabFocus;
429
430 if ( !tabFocus && window() )
431 {
432 // removing the activeFocusItem from the focus tab chain is not possible
433 if ( window()->activeFocusItem() == this )
434 {
435 if ( auto focusItem = nextItemInFocusChain( true ) )
436 focusItem->setFocus( true );
437 }
438 }
439
440 Inherited::setActiveFocusOnTab( tabFocus );
441
442 Q_EMIT focusPolicyChanged( focusPolicy() );
443 }
444}
445
446Qt::FocusPolicy QskItem::focusPolicy() const
447{
448 uint policy = d_func()->focusPolicy;
449 if ( Inherited::activeFocusOnTab() )
450 policy |= Qt::TabFocus;
451
452 return static_cast< Qt::FocusPolicy >( policy );
453}
454
455void QskItem::setWheelEnabled( bool on )
456{
457 Q_D( QskItem );
458 if ( on != d->wheelEnabled )
459 {
460 d->wheelEnabled = on;
461 Q_EMIT wheelEnabledChanged( on );
462 }
463}
464
465bool QskItem::isWheelEnabled() const
466{
467 return d_func()->wheelEnabled;
468}
469
471{
472 Q_D( QskItem );
473 if ( on != d->polishOnResize )
474 {
475 d->polishOnResize = on;
476 polish();
477
478 Q_EMIT itemFlagsChanged();
479 }
480}
481
483{
484 return d_func()->polishOnResize;
485}
486
487void QskItem::setPolishOnParentResize( bool on )
488{
489 Q_D( QskItem );
490 if ( on != d->polishOnParentResize )
491 {
492 d->polishOnParentResize = on;
493
494 if ( parentItem() && qskParentListener )
495 {
496 qskParentListener->update( parentItem() );
497
499 polish();
500 }
501
502 Q_EMIT itemFlagsChanged();
503 }
504}
505
506bool QskItem::polishOnParentResize() const
507{
508 return d_func()->polishOnParentResize;
509}
510
512{
513#if 1
514 /*
515 What about using Qt::LayoutDirection instead. It sounds
516 like a more expressive API and we do not run into conflicts
517 with the layoutMirroring() attached property for QML.
518 But what is the situation with locales, where the default direction
519 is RightToLeft ?
520 */
521 return d_func()->effectiveLayoutMirror;
522#endif
523}
524
525void QskItem::setLayoutMirroring( bool on, bool childrenInherit )
526{
527 // Again we have to deal with an existing API made for QML,
528 // that is weired for C++: LayoutMirroring/QQuickLayoutMirroringAttached
529 // Internally it is managed by 5(!) different flags - condolences
530 // to the poor guy who has been sentenced to maintain this.
531
532 // Anyway, the code below might achieve the desired behavior without
533 // breaking the QML path.
534
535 Q_D( QQuickItem );
536
537 if ( childrenInherit != d->inheritMirrorFromItem )
538 {
539 d->inheritMirrorFromItem = childrenInherit;
540 d->resolveLayoutMirror();
541 }
542
543 d->isMirrorImplicit = false;
544
545 if ( on != d->effectiveLayoutMirror )
546 {
547 d->setLayoutMirror( on );
548 if ( childrenInherit )
549 d->resolveLayoutMirror();
550 }
551}
552
554{
555 Q_D( QQuickItem );
556
557 if ( d && !d->isMirrorImplicit )
558 {
559 d->isMirrorImplicit = true;
560 // d->inheritMirrorFromItem = false;
561 d->resolveLayoutMirror();
562 }
563}
564
566{
567 return d_func()->polishScheduled;
568}
569
571{
572 Q_D( const QskItem );
573
574 return ( d->dirtyAttributes & QQuickItemPrivate::ContentUpdateMask ) &&
575 ( d->flags & QQuickItem::ItemHasContents );
576}
577
579{
580 return d_func()->initiallyPainted;
581}
582
584{
585 Q_D( const QskItem );
586
587 if ( d->width <= 0.0 && d->height <= 0.0 )
588 {
589 /*
590 Unfortunately the list of items to-be-polished is not processed
591 in top/down order and we might run into updatePolish() before
592 having a proper size. But when the parentItem() is waiting
593 for to-be-polished, we assume, that we will be resized then
594 and run into another updatePolish() then.
595 */
596 if ( d->polishOnResize && qskIsPolishScheduled( parentItem() ) )
597 return true;
598 }
599
600 return false;
601}
602
603QskItem::UpdateFlags QskItem::updateFlags() const
604{
605 return UpdateFlags( d_func()->updateFlags );
606}
607
609{
610 Q_D( QskItem );
611
612 // clear all bits in the mask
613 d->updateFlagsMask = 0;
614 d->applyUpdateFlags( QskSetup::updateFlags() );
615}
616
618{
619 Q_D( QskItem );
620
621 d->updateFlagsMask |= flag;
622
623 if ( testUpdateFlag( flag ) != on )
624 {
625 applyUpdateFlag( flag, on );
627 }
628}
629
631{
632 Q_D( QskItem );
633
634 d->updateFlagsMask &= ~flag;
635
636 const bool on = QskSetup::testUpdateFlag( flag );
637
638 if ( testUpdateFlag( flag ) != on )
639 {
640 applyUpdateFlag( flag, on );
642 }
643}
644
646{
647 return d_func()->updateFlags & flag;
648}
649
650void QskItem::applyUpdateFlag( UpdateFlag flag, bool on )
651{
652 Q_D( QskItem );
653
654 if ( testUpdateFlag( flag ) == on )
655 return;
656
657 if ( on )
658 d->updateFlags |= flag;
659 else
660 d->updateFlags &= ~flag;
661
662 switch ( flag )
663 {
665 {
666 if ( on )
667 {
668 qskFilterWindow( window() );
669 }
670 else
671 {
672 if ( !isVisible() )
673 update();
674 }
675
676 break;
677 }
679 {
680 if ( !on && d->blockedPolish )
681 polish();
682
683 break;
684 }
686 {
687 if ( !on )
688 {
689 // Update the implicitSize and rebind the size to it.
690 // Having set the size explicitly gets lost.
691
692#if QT_VERSION >= QT_VERSION_CHECK( 6, 2, 0 )
693 d->widthValidFlag = d->heightValidFlag = false;
694#else
695 d->widthValid = d->heightValid = false;
696#endif
697 d->updateImplicitSize( false );
698 }
699
700 break;
701 }
703 {
704 if ( on && !isVisible() )
705 d->cleanupNodes();
706
707 break;
708 }
710 {
711 // no need to mark it dirty
712 if ( flags() & QQuickItem::ItemHasContents )
713 update();
714 break;
715 }
716 default:
717 break;
718 }
719}
720
722{
723 Q_D( QskItem );
724
725 if ( d->updateFlags & QskItem::DeferredLayout )
726 {
727 d->blockedImplicitSize = true;
728 d->layoutConstraintChanged();
729 }
730 else
731 {
732 d->updateImplicitSize( true );
733 }
734}
735
736bool QskItem::event( QEvent* event )
737{
738 const int eventType = event->type();
739 const bool hasContents = flags() & QQuickItem::ItemHasContents;
740
741 switch( eventType )
742 {
743 case QEvent::StyleChange:
744 {
745 d_func()->clearPreviousNodes = true;
746
748 polish();
749
750 if ( hasContents )
751 update();
752
754 return true;
755 }
756 case QEvent::ContentsRectChange:
757 {
759
760 if ( d_func()->polishOnResize )
761 polish();
762
763 if ( hasContents )
764 update();
765
767 return true;
768 }
769 case QEvent::ReadOnlyChange:
770 case QEvent::EnabledChange:
771 case QEvent::LocaleChange:
772 case QEvent::ParentChange:
773 case QEvent::LayoutDirectionChange:
774 {
776 return true;
777 }
778 case QskEvent::GeometryChange:
779 {
781 return true;
782 }
783 case QskEvent::WindowChange:
784 {
785 windowChangeEvent( static_cast< QskWindowChangeEvent* >( event ) );
786 return true;
787 }
788 case QEvent::LayoutRequest:
789 {
790 if ( d_func()->polishOnResize )
791 polish();
792
793 return true;
794 }
795 case QEvent::FocusIn:
796 {
797 if ( window() == nullptr )
798 {
799 /*
800 During deconstruction of the window we run into
801 focus changes when the items in the tree get destroyed.
802 Calling focusInEvent() in this state does not make sense
803 and often results in crashes in overloaded event handlers.
804 */
805 return true;
806 }
807
808 break;
809 }
810 case QEvent::MouseButtonPress:
811 case QEvent::MouseButtonRelease:
812 {
813 if ( ( focusPolicy() & Qt::ClickFocus ) == Qt::ClickFocus )
814 {
815 if ( QGuiApplication::styleHints()->setFocusOnTouchRelease() )
816 {
817 if ( event->type() == QEvent::MouseButtonRelease )
818 forceActiveFocus( Qt::MouseFocusReason );
819 }
820 else
821 {
822 if ( event->type() == QEvent::MouseButtonPress )
823 forceActiveFocus( Qt::MouseFocusReason );
824 }
825 }
826 break;
827 }
828 case QEvent::Wheel:
829 {
830 if ( !isWheelEnabled() )
831 {
832 /*
833 We block further processing of the event. This is in line
834 with not receiving any mouse event that have not been
835 explicitly enabled with setAcceptedMouseButtons().
836 */
837 event->ignore();
838 return true;
839 }
840
841 if ( ( focusPolicy() & Qt::WheelFocus ) == Qt::WheelFocus )
842 forceActiveFocus( Qt::MouseFocusReason );
843
844 break;
845 }
846 }
847
848 return Inherited::event( event );
849}
850
854
858
859void QskItem::changeEvent( QEvent* )
860{
861}
862
863void QskItem::itemChange( QQuickItem::ItemChange change,
864 const QQuickItem::ItemChangeData& changeData )
865{
866 switch ( change )
867 {
868 case QQuickItem::ItemSceneChange:
869 {
870 if ( changeData.window )
871 {
872 Q_D( const QskItem );
873 if ( d->updateFlags & QskItem::DeferredUpdate )
874 qskFilterWindow( changeData.window );
875 }
876
877#if 1
878 auto oldWindow = qskReleasedWindowCounter->window();
879
880 if ( oldWindow && oldWindow->contentItem()
881 && ( oldWindow->activeFocusItem() == this ) )
882 {
883 /*
884 Removing an item from the scene might result in
885 changes of the active focus item. Unfortunately the corresponding
886 FocusIn/Out events are sent, while the item tree is in an
887 invalid state.
888 When having event handlers, that do modifications of the focus
889 ( f.e. assigning the local focus, inside of a focus scope )
890 we might end up with having a dangling pointer for
891 oldWindow->activeFocusItem().
892 */
893
894#if QT_VERSION >= QT_VERSION_CHECK( 6, 1, 0 )
895 auto wd = QQuickWindowPrivate::get( oldWindow )->deliveryAgentPrivate();
896#else
897 auto wd = QQuickWindowPrivate::get( oldWindow );
898#endif
899 if ( auto scope = qskNearestFocusScope( this ) )
900 {
901 wd->clearFocusInScope( scope, this, Qt::OtherFocusReason );
902 }
903 else
904 {
905 wd->activeFocusItem = nullptr;
906 }
907 }
908#endif
909
910#if 1
911 if ( changeData.window == nullptr )
912 {
913 Q_D( QskItem );
914
915 if( d->focus )
916 {
917 /*
918 The focus flag is not cleared, when removing an
919 item from the window. In situations where the item gets
920 reinserted into the window - or transferred to another one -
921 we might run into situations, where 2 items in the same scope
922 have the "focus" flag being set.
923 A better solution might be to check the flag when reinserting
924 into a window ...
925 */
926 d->focus = false;
927 }
928 }
929#endif
930
931 QskWindowChangeEvent event( oldWindow, changeData.window );
932 QCoreApplication::sendEvent( this, &event );
933
934 break;
935 }
936 case QQuickItem::ItemEnabledHasChanged:
937 {
938 qskSendEventTo( this, QEvent::EnabledChange );
939 break;
940 }
941 case QQuickItem::ItemVisibleHasChanged:
942 {
943 Q_D( QskItem );
944#if 1
945 /*
946 ~QQuickItem sends QQuickItem::ItemVisibleHasChanged recursively
947 to all childItems. When being a child ( not only a childItem() )
948 we are short before being destructed too and any updates
949 done here are totally pointless. TODO ...
950 */
951#endif
952 if ( changeData.boolValue )
953 {
954 if ( d->blockedPolish )
955 polish();
956
957 if ( d->updateFlags & QskItem::DeferredUpdate )
958 {
959 if ( d->dirtyAttributes && ( d->flags & QQuickItem::ItemHasContents ) )
960 update();
961 }
962 }
963 else
964 {
965 if ( d->updateFlags & QskItem::CleanupOnVisibility )
966 d->cleanupNodes();
967
968 d->initiallyPainted = false;
969 }
970
971 if ( parentItem() && parentItem()->isVisible() )
972 {
973 /*
974 Layout code might consider the visiblility of the children
975 and therefore needs to be updated. Posting a statement about
976 changed layout constraints has this effect, but is not correct.
977 The right way to go would be to create show/hide events and to
978 handle them, where visibility of the children matters.
979 TODO ...
980 */
981
982 d->layoutConstraintChanged();
983 }
984
985 break;
986 }
987 case QQuickItem::ItemParentHasChanged:
988 {
989 if( polishOnParentResize() && qskParentListener )
990 qskParentListener->update( parentItem() );
991
992 break;
993 }
994 case QQuickItem::ItemChildAddedChange:
995 case QQuickItem::ItemChildRemovedChange:
996 {
997 // do we want to have events for those ???
998 break;
999 }
1000
1001 case QQuickItem::ItemOpacityHasChanged:
1002 case QQuickItem::ItemActiveFocusHasChanged:
1003 case QQuickItem::ItemRotationHasChanged:
1004 case QQuickItem::ItemAntialiasingHasChanged:
1005 case QQuickItem::ItemDevicePixelRatioHasChanged:
1006 {
1007 break;
1008 }
1009 }
1010
1011 Inherited::itemChange( change, changeData );
1012}
1013
1014#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
1015
1016void QskItem::geometryChanged(
1017 const QRectF& newGeometry, const QRectF& oldGeometry )
1018{
1019 geometryChange( newGeometry, oldGeometry );
1020}
1021
1022#endif
1023
1025 const QRectF& newGeometry, const QRectF& oldGeometry )
1026{
1027#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
1028 Inherited::geometryChanged( newGeometry, oldGeometry );
1029#else
1030 Inherited::geometryChange( newGeometry, oldGeometry );
1031#endif
1032
1033 Q_D( const QskItem );
1034 if ( !d->polishScheduled && d->polishOnResize )
1035 {
1036 if ( newGeometry.size() != oldGeometry.size() )
1037 polish();
1038 }
1039
1040 QskGeometryChangeEvent event( newGeometry, oldGeometry );
1041 QCoreApplication::sendEvent( this, &event );
1042}
1043
1045{
1046 Inherited::mouseUngrabEvent();
1047}
1048
1050{
1051 Inherited::touchUngrabEvent();
1052}
1053
1054#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
1055
1056void QskItem::windowDeactivateEvent()
1057{
1058 Inherited::windowDeactivateEvent();
1059}
1060
1061#endif
1062
1063void QskItem::updatePolish()
1064{
1065 Q_D( QskItem );
1066
1067 if ( d->updateFlags & QskItem::DeferredPolish )
1068 {
1069 if ( !isVisible() )
1070 {
1071 d->blockedPolish = true;
1072 return;
1073 }
1074 }
1075
1076 d->blockedPolish = false;
1077
1078 if ( !d->initiallyPainted )
1079 {
1080 /*
1081 We should find a better way for identifying, when
1082 an item is about to be shown, than making it dependend
1083 from polishing and the existence of scene graph nodes. TODO ...
1084 */
1085 aboutToShow();
1086 }
1087
1088 updateItemPolish();
1089}
1090
1092{
1093}
1094
1095void QskItem::updateItemPolish()
1096{
1097}
1098
1099QSGNode* QskItem::updatePaintNode( QSGNode* node, UpdatePaintNodeData* data )
1100{
1101 Q_UNUSED( data )
1102
1103 Q_D( QskItem );
1104
1105 Q_ASSERT( isVisible() || !( d->updateFlags & QskItem::DeferredUpdate ) );
1106
1107 d->initiallyPainted = true;
1108
1109 if ( d->clearPreviousNodes )
1110 {
1111 delete node;
1112 node = nullptr;
1113#if 1
1114 /*
1115 controls might find subnodes using qskPaintNode - not good
1116 as d->paintNode is not updated before leaving here. TODO ...
1117
1118 In the initial call we will always have a nullptr - even if
1119 it has already been allocated. When deleting it we have a dangling pointer.
1120 instead of the new one.
1121
1122 To avoid creashes for the second situation we manually clear d->paintNode.
1123 */
1124 d->paintNode = nullptr;
1125#endif
1126
1127 d->clearPreviousNodes = false;
1128 }
1129
1130 return updateItemPaintNode( node );
1131}
1132
1133QSGNode* QskItem::updateItemPaintNode( QSGNode* node )
1134{
1135 return node;
1136}
1137
1138void qskUpdateItemFlags()
1139{
1140 if ( qskRegistry )
1141 qskRegistry->updateItemFlags();
1142}
1143
1144#include "moc_QskItem.cpp"
bool isPolishScheduled() const
Definition QskItem.cpp:565
void mouseUngrabEvent() override
Definition QskItem.cpp:1044
void setTabFence(bool)
Definition QskItem.cpp:400
void show()
Definition QskItem.cpp:310
bool polishOnResize
Definition QskItem.h:27
bool isVisibleToParent() const
Definition QskItem.cpp:325
void geometryChange(const QRectF &, const QRectF &) override
Definition QskItem.cpp:1024
void setHidden(bool)
Definition QskItem.cpp:305
void resetUpdateFlags()
Definition QskItem.cpp:608
void itemChange(ItemChange, const ItemChangeData &) override
Definition QskItem.cpp:863
bool event(QEvent *) override
Definition QskItem.cpp:736
UpdateFlags updateFlags
Definition QskItem.h:42
void setPolishOnResize(bool)
Definition QskItem.cpp:470
void classBegin() override
Definition QskItem.cpp:267
QRectF rect
Definition QskItem.h:21
void resetImplicitSize()
Definition QskItem.cpp:721
virtual void aboutToShow()
Definition QskItem.cpp:1091
UpdateFlag
Definition QskItem.h:48
@ DebugForceBackground
Definition QskItem.h:56
@ CleanupOnVisibility
Definition QskItem.h:52
@ DeferredPolish
Definition QskItem.h:50
@ DeferredUpdate
Definition QskItem.h:49
@ DeferredLayout
Definition QskItem.h:51
void resetLayoutMirroring()
Definition QskItem.cpp:553
void touchUngrabEvent() override
Definition QskItem.cpp:1049
void releaseResources() override
Definition QskItem.cpp:287
const char * className() const
Definition QskItem.cpp:262
void setDisabled(bool)
Definition QskItem.cpp:300
void itemFlagsChanged()
void setLayoutMirroring(bool on, bool childrenInherit=false)
Definition QskItem.cpp:525
bool isTabFence() const
Definition QskItem.cpp:410
virtual void geometryChangeEvent(QskGeometryChangeEvent *)
Definition QskItem.cpp:855
bool isInitiallyPainted() const
Definition QskItem.cpp:578
void resetUpdateFlag(UpdateFlag)
Definition QskItem.cpp:630
virtual void changeEvent(QEvent *)
Definition QskItem.cpp:859
virtual void windowChangeEvent(QskWindowChangeEvent *)
Definition QskItem.cpp:851
bool isUpdateNodeScheduled() const
Definition QskItem.cpp:570
QRectF geometry
Definition QskItem.h:20
void updateFlagsChanged(UpdateFlags)
bool maybeUnresized() const
Definition QskItem.cpp:583
void setUpdateFlag(UpdateFlag, bool on=true)
Definition QskItem.cpp:617
void hide()
Definition QskItem.cpp:315
bool isVisibleTo(const QQuickItem *) const
Definition QskItem.cpp:320
bool testUpdateFlag(UpdateFlag) const
Definition QskItem.cpp:645
void componentComplete() override
Definition QskItem.cpp:272
void setGeometry(qreal x, qreal y, qreal width, qreal height)
Definition QskItem.cpp:330
bool layoutMirroring() const
Definition QskItem.cpp:511