diff --git a/src/controls/QskMenu.cpp b/src/controls/QskMenu.cpp index 22f9caef..5cc62a05 100644 --- a/src/controls/QskMenu.cpp +++ b/src/controls/QskMenu.cpp @@ -238,18 +238,6 @@ void QskMenu::traverse( int steps ) Q_EMIT currentIndexChanged( index ); } -int QskMenu::indexAtPosition( const QPointF& pos ) const -{ - for ( int i = 0; i < count(); i++ ) - { - // A menu never has many cells and we can simply iterate - if ( cellRect( i ).contains( pos ) ) - return i; - } - - return -1; -} - QskColorFilter QskMenu::graphicFilterAt( int index ) const { Q_UNUSED( index ); @@ -314,4 +302,10 @@ QRectF QskMenu::cellRect( int index ) const this, contentsRect(), QskMenu::Cell, index ); } +int QskMenu::indexAtPosition( const QPointF& pos ) const +{ + return effectiveSkinlet()->itemIndexAt( + this, contentsRect(), QskMenu::Cell, pos ); +} + #include "moc_QskMenu.cpp" diff --git a/src/controls/QskMenu.h b/src/controls/QskMenu.h index 80a31951..61a4bf5d 100644 --- a/src/controls/QskMenu.h +++ b/src/controls/QskMenu.h @@ -50,7 +50,6 @@ class QSK_EXPORT QskMenu : public QskPopup void addSeparator(); - int indexAtPosition( const QPointF& ) const; Entry entryAt( int index ) const; QskGraphic graphicAt( int index ) const; @@ -65,6 +64,7 @@ class QSK_EXPORT QskMenu : public QskPopup QRectF focusIndicatorRect() const override; QRectF cellRect( int index ) const; + int indexAtPosition( const QPointF& ) const; Q_SIGNALS: void triggered( int index ); diff --git a/src/controls/QskMenuSkinlet.cpp b/src/controls/QskMenuSkinlet.cpp index 63436cab..b452dbc6 100644 --- a/src/controls/QskMenuSkinlet.cpp +++ b/src/controls/QskMenuSkinlet.cpp @@ -271,6 +271,41 @@ QRectF QskMenuSkinlet::itemRect( skinnable, contentsRect, subControl, index ); } +int QskMenuSkinlet::itemIndexAt( const QskSkinnable* skinnable, + const QRectF& rect, QskAspect::Subcontrol subControl, const QPointF& pos ) const +{ + if ( subControl == QskMenu::Cell ) + { + const auto menu = static_cast< const QskMenu* >( skinnable ); + + const auto panelRect = menu->subControlContentsRect( QskMenu::Panel ); + if ( !panelRect.contains( pos ) ) + return -1; + + /* + A menu never has many items and we can simply iterate + without being concerned about performance issues + */ + + const auto h = qskCellHeight( menu ); + + auto r = panelRect; + r.setHeight( h ); + + for ( int i = 0; i < menu->count(); i++ ) + { + if ( r.contains( pos ) ) + return i; + + r.moveTop( r.bottom() ); + } + + return -1; + } + + return Inherited::itemIndexAt( skinnable, rect, subControl, pos ); +} + QSGNode* QskMenuSkinlet::updateContentsNode( const QskPopup* popup, QSGNode* contentsNode ) const { diff --git a/src/controls/QskMenuSkinlet.h b/src/controls/QskMenuSkinlet.h index 4b557810..9527a03d 100644 --- a/src/controls/QskMenuSkinlet.h +++ b/src/controls/QskMenuSkinlet.h @@ -24,7 +24,10 @@ class QSK_EXPORT QskMenuSkinlet : public QskPopupSkinlet const QRectF&, QskAspect::Subcontrol ) const override; QRectF itemRect( const QskSkinnable*, - const QRectF&, QskAspect::Subcontrol, int index ) const override; + const QRectF&, QskAspect::Subcontrol, int itemIndex ) const override; + + int itemIndexAt( const QskSkinnable*, + const QRectF&, QskAspect::Subcontrol, const QPointF& ) const override; QSizeF sizeHint( const QskSkinnable*, Qt::SizeHint, const QSizeF& ) const override; diff --git a/src/controls/QskSkinlet.cpp b/src/controls/QskSkinlet.cpp index 2b1a7baf..a4bd9033 100644 --- a/src/controls/QskSkinlet.cpp +++ b/src/controls/QskSkinlet.cpp @@ -581,6 +581,12 @@ QSizeF QskSkinlet::hintWithoutConstraint( return h; } +int QskSkinlet::itemIndexAt( const QskSkinnable*, + const QRectF&, QskAspect::Subcontrol, const QPointF& ) const +{ + return -1; +} + QRectF QskSkinlet::itemRect( const QskSkinnable*, const QRectF&, QskAspect::Subcontrol, int index ) const { diff --git a/src/controls/QskSkinlet.h b/src/controls/QskSkinlet.h index 7aef1716..90b69568 100644 --- a/src/controls/QskSkinlet.h +++ b/src/controls/QskSkinlet.h @@ -36,14 +36,17 @@ class QSK_EXPORT QskSkinlet virtual void updateNode( QskSkinnable*, QSGNode* parent ) const; + virtual QSizeF sizeHint( const QskSkinnable*, + Qt::SizeHint, const QSizeF& ) const; + virtual QRectF subControlRect( const QskSkinnable*, const QRectF&, QskAspect::Subcontrol ) const; virtual QRectF itemRect( const QskSkinnable*, - const QRectF&, QskAspect::Subcontrol, int index ) const; + const QRectF&, QskAspect::Subcontrol, int itemIndex ) const; - virtual QSizeF sizeHint( const QskSkinnable*, - Qt::SizeHint, const QSizeF& ) const; + virtual int itemIndexAt( const QskSkinnable*, + const QRectF&, QskAspect::Subcontrol, const QPointF& ) const; const QVector< quint8 >& nodeRoles() const;