diff --git a/src/controls/QskMenu.cpp b/src/controls/QskMenu.cpp index cfbd285d..721246cb 100644 --- a/src/controls/QskMenu.cpp +++ b/src/controls/QskMenu.cpp @@ -7,6 +7,7 @@ #include #include +#include QSK_SUBCONTROL( QskMenu, Panel ) QSK_SUBCONTROL( QskMenu, Cell ) @@ -16,11 +17,20 @@ QSK_SUBCONTROL( QskMenu, Graphic ) QSK_SYSTEM_STATE( QskMenu, Selected, QskAspect::FirstSystemState << 2 ) +namespace +{ + struct Entry + { + QUrl graphicSource; + QskGraphic graphic; + QString text; + }; +} + class QskMenu::PrivateData { public: QVector< Entry > entries; - QVector< QskGraphic > icons; QskTextOptions textOptions; QPointF origin; @@ -81,29 +91,17 @@ QPointF QskMenu::origin() const void QskMenu::addItem( const QUrl& graphicSource, const QString& text ) { - m_data->entries += { graphicSource, text }; + QskGraphic graphic; + if( !graphicSource.isEmpty() ) + graphic = Qsk::loadGraphic( graphicSource ); -#if 1 - { - const auto& entries = m_data->entries; - - m_data->icons.clear(); - m_data->icons.reserve( entries.count() ); - - for( const auto& entry : entries ) - { - QskGraphic graphic; - - if( !entry.iconSource.isEmpty() ) - graphic = Qsk::loadGraphic( entry.iconSource ); - - m_data->icons += graphic; - } - } -#endif + m_data->entries += { graphicSource, graphic, text }; resetImplicitSize(); update(); + + if ( isComponentComplete() ) + countChanged( count() ); } void QskMenu::addItem( const QString& graphicSource, const QString& text ) @@ -118,7 +116,6 @@ void QskMenu::addSeparator() void QskMenu::clear() { - m_data->icons.clear(); m_data->entries.clear(); } @@ -127,24 +124,20 @@ int QskMenu::count() const return m_data->entries.count(); } -QskMenu::Entry QskMenu::entryAt( int index ) const +QVariant QskMenu::itemAt( int index ) const { - if( index >= 0 && index <= m_data->entries.count() ) - { - return m_data->entries[ index ]; - } + const auto& entries = m_data->entries; - return Entry(); -} + if( index < 0 || index >= entries.count() ) + return QVariant(); -QskGraphic QskMenu::graphicAt( int index ) const -{ - if( index >= 0 && index <= m_data->icons.count() ) - { - return m_data->icons[ index ]; - } + const auto& entry = m_data->entries[ index ]; - return QskGraphic(); + QVariantList list; + list += QVariant::fromValue( entry.graphic ); + list += QVariant::fromValue( entry.text ); + + return list; } void QskMenu::setTextOptions( const QskTextOptions& textOptions ) diff --git a/src/controls/QskMenu.h b/src/controls/QskMenu.h index 89fffccb..f56198b9 100644 --- a/src/controls/QskMenu.h +++ b/src/controls/QskMenu.h @@ -24,7 +24,7 @@ class QSK_EXPORT QskMenu : public QskPopup Q_PROPERTY( bool cascading READ isCascading WRITE setCascading RESET resetCascading NOTIFY cascadingChanged ) - Q_PROPERTY( int count READ count ) + Q_PROPERTY( int count READ count NOTIFY countChanged ) Q_PROPERTY( int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged ) @@ -32,12 +32,6 @@ class QSK_EXPORT QskMenu : public QskPopup using Inherited = QskPopup; public: - struct Entry - { - QUrl iconSource; - QString text; - }; - QSK_SUBCONTROLS( Panel, Cell, Cursor, Text, Graphic ) QSK_STATES( Selected ) @@ -57,14 +51,14 @@ class QSK_EXPORT QskMenu : public QskPopup void addSeparator(); - Entry entryAt( int index ) const; - QskGraphic graphicAt( int index ) const; + virtual QVariant itemAt( int ) const; + virtual int count() const; + virtual void clear(); void setTextOptions( const QskTextOptions& textOptions ); QskTextOptions textOptions() const; int currentIndex() const; - int count() const; virtual QskColorFilter graphicFilterAt( int index ) const; QRectF focusIndicatorRect() const override; @@ -79,9 +73,10 @@ class QSK_EXPORT QskMenu : public QskPopup void triggered( int index ); void currentIndexChanged( int index ); + void countChanged( int ); + public Q_SLOTS: void setCurrentIndex( int index ); - void clear(); protected: void keyPressEvent( QKeyEvent* ) override; diff --git a/src/controls/QskMenuSkinlet.cpp b/src/controls/QskMenuSkinlet.cpp index b452dbc6..503cd389 100644 --- a/src/controls/QskMenuSkinlet.cpp +++ b/src/controls/QskMenuSkinlet.cpp @@ -27,6 +27,27 @@ namespace }; } +template< class T > +static T qskValueAt( const QskMenu* menu, int index ) +{ + const auto item = menu->itemAt( index ); + + if ( item.canConvert< T >() ) + return item.value< T >(); + + if ( item.canConvert< QVariantList >() ) + { + const auto list = item.value< QVariantList >(); + for ( const auto& value : list ) + { + if ( value.canConvert< T >() ) + return value.value< T >(); + } + } + + return T(); +} + static qreal qskMaxTextWidth( const QskMenu* menu ) { const QFontMetricsF fm( menu->effectiveFont( QskMenu::Text ) ); @@ -35,10 +56,12 @@ static qreal qskMaxTextWidth( const QskMenu* menu ) for ( int i = 0; i < menu->count(); i++ ) { - const auto entry = menu->entryAt( i ); - if( !entry.text.isEmpty() ) + const auto value = menu->itemAt( i ); + + const auto text = qskValueAt< QString >( menu, i ); + if( !text.isEmpty() ) { - const auto w = qskHorizontalAdvance( fm, entry.text ); + const auto w = qskHorizontalAdvance( fm, text ); if( w > maxWidth ) maxWidth = w; } @@ -57,7 +80,8 @@ static qreal qskGraphicWidth( const QskMenu* menu ) qreal maxW = 0.0; for ( int i = 0; i < menu->count(); i++ ) { - const auto w = menu->graphicAt( i ).widthForHeight( h ); + const auto graphic = qskValueAt< QskGraphic >( menu, i ); + const auto w = graphic.widthForHeight( h ); if( w > maxW ) maxW = w; } @@ -215,8 +239,11 @@ static QSGNode* qskUpdateItemsNode( const QskMenu* menu, QSGNode* rootNode ) auto textRect = cellRect; textRect.setX( graphicRect.right() + spacing ); - qskUpdateItemNode( menu, graphicRect, menu->graphicAt( i ), - textRect, menu->entryAt( i ).text, node ); + const auto graphic = qskValueAt< QskGraphic >( menu, i ); + const auto text = qskValueAt< QString >( menu, i ); + + qskUpdateItemNode( menu, graphicRect, graphic, + textRect, text, node ); } } diff --git a/src/controls/QskMenuSkinlet.h b/src/controls/QskMenuSkinlet.h index 9527a03d..1d6cf444 100644 --- a/src/controls/QskMenuSkinlet.h +++ b/src/controls/QskMenuSkinlet.h @@ -24,7 +24,7 @@ class QSK_EXPORT QskMenuSkinlet : public QskPopupSkinlet const QRectF&, QskAspect::Subcontrol ) const override; QRectF itemRect( const QskSkinnable*, - const QRectF&, QskAspect::Subcontrol, int itemIndex ) const override; + const QRectF&, QskAspect::Subcontrol, int index ) const override; int itemIndexAt( const QskSkinnable*, const QRectF&, QskAspect::Subcontrol, const QPointF& ) const override;