diff --git a/src/controls/QskComboBox.cpp b/src/controls/QskComboBox.cpp index 42e7019b..c542aab5 100644 --- a/src/controls/QskComboBox.cpp +++ b/src/controls/QskComboBox.cpp @@ -218,8 +218,7 @@ void QskComboBox::openPopup() menu->setOrigin( mapToScene( cr.bottomLeft() ) ); menu->setFixedWidth( cr.width() ); - for ( const auto& option : m_data->options ) - menu->addOption( option.icon().graphic(), option.text() ); + menu->setOptions( m_data->options ); connect( menu, &QskMenu::currentIndexChanged, this, &QskComboBox::indexInPopupChanged ); diff --git a/src/controls/QskMenu.cpp b/src/controls/QskMenu.cpp index c248e74b..d7bceb05 100644 --- a/src/controls/QskMenu.cpp +++ b/src/controls/QskMenu.cpp @@ -6,6 +6,7 @@ #include "QskMenu.h" #include "QskGraphicProvider.h" +#include "QskLabelData.h" #include "QskTextOptions.h" #include "QskGraphic.h" #include "QskColorFilter.h" @@ -27,47 +28,15 @@ QSK_SUBCONTROL( QskMenu, Separator ) QSK_SYSTEM_STATE( QskMenu, Selected, QskAspect::FirstSystemState << 2 ) -namespace -{ - class Option - { - public: - Option( const QskGraphic& graphic, const QString& text ) - : text( text ) - , graphic( graphic ) - { - } - - Option( const QUrl& graphicSource, const QString& text ) - : graphicSource( graphicSource ) - , text( text ) - { -#if 1 - // lazy loading TODO ... - if( !graphicSource.isEmpty() ) - graphic = Qsk::loadGraphic( graphicSource ); -#endif - } - - QUrl graphicSource; - QString text; - - QskGraphic graphic; - -#if 0 - // TODO ... - bool isEnabled = true; -#endif - }; -} - class QskMenu::PrivateData { public: - QVector< Option > options; + QPointF origin; + + QVector< QskLabelData > options; + // QVector< bool > enabled; QVector< int > separators; - QPointF origin; // current/selected are not well defined yet, TODO ... int currentIndex = -1; @@ -135,36 +104,81 @@ QPointF QskMenu::origin() const return m_data->origin; } -void QskMenu::addOption( const QString& text ) +void QskMenu::setTextOptions( const QskTextOptions& textOptions ) { - addOption( QUrl(), text ); + setTextOptionsHint( Text, textOptions ); } -void QskMenu::addOption( const QUrl& graphicSource, const QString& text ) +QskTextOptions QskMenu::textOptions() const { - m_data->options += Option( graphicSource, text ); + return textOptionsHint( Text ); +} + +int QskMenu::addOption( const QString& graphicSource, const QString& text ) +{ + return addOption( QskLabelData( text, graphicSource ) ); +} + +int QskMenu::addOption( const QUrl& graphicSource, const QString& text ) +{ + return addOption( QskLabelData( text, graphicSource ) ); +} + +int QskMenu::addOption( const QskLabelData& option ) +{ + m_data->options += option; resetImplicitSize(); update(); if ( isComponentComplete() ) - Q_EMIT countChanged( count() ); + Q_EMIT optionsChanged(); + + return count() - 1; } -void QskMenu::addOption( const QskGraphic& graphic, const QString& text ) +void QskMenu::setOptions( const QVector< QskLabelData >& options ) { - m_data->options += Option( graphic, text ); + m_data->options = options; + m_data->selectedIndex = -1; + + if ( m_data->currentIndex >= 0 ) + { + m_data->currentIndex = -1; + + if ( isComponentComplete() ) + Q_EMIT currentIndexChanged( m_data->currentIndex ); + } resetImplicitSize(); update(); if ( isComponentComplete() ) - Q_EMIT countChanged( count() ); + Q_EMIT optionsChanged(); } -void QskMenu::addOption( const QString& graphicSource, const QString& text ) +void QskMenu::clear() { - addOption( QUrl( graphicSource ), text ); + m_data->selectedIndex = m_data->currentIndex = -1; + m_data->separators.clear(); + + if ( !m_data->options.isEmpty() ) + { + m_data->options.clear(); + + if ( isComponentComplete() ) + Q_EMIT optionsChanged(); + } +} + +QVector< QskLabelData > QskMenu::options() const +{ + return m_data->options; +} + +QskLabelData QskMenu::optionAt( int index ) const +{ + return m_data->options.value( index ); } int QskMenu::count() const @@ -190,55 +204,12 @@ int QskMenu::separatorCount() const return m_data->separators.count(); } -void QskMenu::clear() -{ - m_data->separators.clear(); - - if ( !m_data->options.isEmpty() ) - { - m_data->options.clear(); - if ( isComponentComplete() ) - Q_EMIT countChanged( count() ); - } -} - -QVariantList QskMenu::optionAt( int index ) const -{ - const auto& options = m_data->options; - - if( index < 0 || index >= options.count() ) - return QVariantList(); - - const auto& option = options[ index ]; - - QVariantList list; - list += QVariant::fromValue( option.graphic ); - list += QVariant::fromValue( option.text ); - - return list; -} - -QString QskMenu::textAt( int index ) const -{ - if ( index >= 0 && index < m_data->options.count() ) - return m_data->options[ index ].text; - - return QString(); -} - QString QskMenu::currentText() const { - return textAt( m_data->currentIndex ); -} + if ( m_data->currentIndex >= 0 ) + return optionAt( m_data->currentIndex ).text(); -void QskMenu::setTextOptions( const QskTextOptions& textOptions ) -{ - setTextOptionsHint( Text, textOptions ); -} - -QskTextOptions QskMenu::textOptions() const -{ - return textOptionsHint( Text ); + return QString(); } void QskMenu::setCurrentIndex( int index ) @@ -374,6 +345,12 @@ void QskMenu::mousePressEvent( QMouseEvent* event ) Inherited::mousePressEvent( event ); } +void QskMenu::mouseUngrabEvent() +{ + m_data->isPressed = false; + Inherited::mouseUngrabEvent(); +} + void QskMenu::mouseReleaseEvent( QMouseEvent* event ) { if ( event->button() == Qt::LeftButton ) diff --git a/src/controls/QskMenu.h b/src/controls/QskMenu.h index deb7545b..9ca3da04 100644 --- a/src/controls/QskMenu.h +++ b/src/controls/QskMenu.h @@ -12,7 +12,7 @@ #include class QskTextOptions; -class QskGraphic; +class QskLabelData; class QSK_EXPORT QskMenu : public QskPopup { @@ -24,7 +24,10 @@ class QSK_EXPORT QskMenu : public QskPopup Q_PROPERTY( bool cascading READ isCascading WRITE setCascading RESET resetCascading NOTIFY cascadingChanged ) - Q_PROPERTY( int count READ count NOTIFY countChanged ) + Q_PROPERTY( QVector< QskLabelData > options READ options + WRITE setOptions NOTIFY optionsChanged ) + + Q_PROPERTY( int count READ count ) Q_PROPERTY( int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged ) @@ -50,14 +53,14 @@ class QSK_EXPORT QskMenu : public QskPopup void setTextOptions( const QskTextOptions& ); QskTextOptions textOptions() const; - // insert, remove, functors, actions - void addOption( const QUrl& iconSource, const QString& text ); - void addOption( const QString& iconSource, const QString& text ); - void addOption( const QskGraphic&, const QString& text ); - void addOption( const QString& text ); + int addOption( const QString&, const QString& ); + int addOption( const QUrl&, const QString& ); + int addOption( const QskLabelData& ); - QVariantList optionAt( int ) const; - QString textAt( int ) const; + void setOptions( const QVector< QskLabelData >& ); + + QVector< QskLabelData > options() const; + QskLabelData optionAt( int ) const; int count() const; @@ -83,12 +86,12 @@ class QSK_EXPORT QskMenu : public QskPopup void originChanged( const QPointF& ); void triggered( int index ); - void currentIndexChanged( int index ); + void currentIndexChanged( int ); - void countChanged( int ); + void optionsChanged(); public Q_SLOTS: - void setCurrentIndex( int index ); + void setCurrentIndex( int ); protected: void keyPressEvent( QKeyEvent* ) override; @@ -99,6 +102,7 @@ class QSK_EXPORT QskMenu : public QskPopup #endif void mousePressEvent( QMouseEvent* ) override; + void mouseUngrabEvent() override; void mouseReleaseEvent( QMouseEvent* ) override; void aboutToShow() override; diff --git a/src/controls/QskMenuSkinlet.cpp b/src/controls/QskMenuSkinlet.cpp index a102050f..e03fada0 100644 --- a/src/controls/QskMenuSkinlet.cpp +++ b/src/controls/QskMenuSkinlet.cpp @@ -13,30 +13,11 @@ #include "QskFunctions.h" #include "QskMargins.h" #include "QskFunctions.h" +#include "QskLabelData.h" #include #include -template< class T > -static inline QVariant qskSampleAt( const QskMenu* menu, int index ) -{ - const auto list = menu->optionAt( index ); - for ( const auto& value : list ) - { - if ( value.canConvert< T >() ) - return value; - } - - return QVariant(); -} - -template< class T > -static inline T qskValueAt( const QskMenu* menu, int index ) -{ - const auto sample = qskSampleAt< T >( menu, index ); - return sample.template value< T >(); -} - class QskMenuSkinlet::PrivateData { public: @@ -415,13 +396,17 @@ QVariant QskMenuSkinlet::sampleAt( const QskSkinnable* skinnable, { using Q = QskMenu; - const auto menu = static_cast< const QskMenu* >( skinnable ); + if ( subControl == Q::Icon || subControl == Q::Text ) + { + const auto menu = static_cast< const QskMenu* >( skinnable ); - if ( subControl == Q::Icon ) - return qskSampleAt< QskGraphic >( menu, index ); + const auto option = menu->optionAt( index ); - if ( subControl == Q::Text ) - return qskSampleAt< QString >( menu, index ); + if ( subControl == Q::Icon ) + return QVariant::fromValue( option.icon().graphic() ); + else + return QVariant::fromValue( option.text() ); + } return Inherited::sampleAt( skinnable, subControl, index ); } @@ -504,7 +489,7 @@ QSGNode* QskMenuSkinlet::updateSampleNode( const QskSkinnable* skinnable, if ( subControl == Q::Icon ) { - const auto graphic = qskValueAt< QskGraphic >( menu, index ); + const auto graphic = menu->optionAt( index ).icon().graphic(); if ( graphic.isNull() ) return nullptr; @@ -517,7 +502,7 @@ QSGNode* QskMenuSkinlet::updateSampleNode( const QskSkinnable* skinnable, if ( subControl == Q::Text ) { - const auto text = qskValueAt< QString >( menu, index ); + const auto text = menu->optionAt( index ).text(); if ( text.isEmpty() ) return nullptr; diff --git a/src/controls/QskSegmentedBar.cpp b/src/controls/QskSegmentedBar.cpp index 57b78f94..57483beb 100644 --- a/src/controls/QskSegmentedBar.cpp +++ b/src/controls/QskSegmentedBar.cpp @@ -110,7 +110,8 @@ int QskSegmentedBar::addOption( const QskLabelData& option ) resetImplicitSize(); update(); - Q_EMIT optionsChanged(); + if ( isComponentComplete() ) + Q_EMIT optionsChanged(); if ( count() == 1 ) setSelectedIndex( 0 ); @@ -325,6 +326,14 @@ int QskSegmentedBar::currentIndex() const return m_data->currentIndex; } +QString QskSegmentedBar::currentText() const +{ + if ( m_data->currentIndex >= 0 ) + return optionAt( m_data->currentIndex ).text(); + + return QString(); +} + void QskSegmentedBar::setSelectedIndex( int index ) { if ( !isSegmentEnabled( index ) ) diff --git a/src/controls/QskSegmentedBar.h b/src/controls/QskSegmentedBar.h index 40e27df0..15e1de23 100644 --- a/src/controls/QskSegmentedBar.h +++ b/src/controls/QskSegmentedBar.h @@ -24,13 +24,15 @@ class QSK_EXPORT QskSegmentedBar : public QskControl Q_PROPERTY( QVector< QskLabelData > options READ options WRITE setOptions NOTIFY optionsChanged ) + Q_PROPERTY( int count READ count ) + Q_PROPERTY( int selectedIndex READ selectedIndex WRITE setSelectedIndex NOTIFY selectedIndexChanged USER true ) Q_PROPERTY( int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged ) - Q_PROPERTY( int count READ count ) + Q_PROPERTY( QString currentText READ currentText ) using Inherited = QskControl; @@ -62,6 +64,8 @@ class QSK_EXPORT QskSegmentedBar : public QskControl int selectedIndex() const; int currentIndex() const; + QString currentText() const; + int count() const; void setSegmentEnabled( int, bool ); diff --git a/src/graphic/QskIcon.h b/src/graphic/QskIcon.h index f4596408..a3047019 100644 --- a/src/graphic/QskIcon.h +++ b/src/graphic/QskIcon.h @@ -37,6 +37,7 @@ class QSK_EXPORT QskIcon public: QskIcon(); + QskIcon( const QString& ); QskIcon( const QUrl& ); QskIcon( const QskGraphic& ); @@ -70,6 +71,11 @@ class QSK_EXPORT QskIcon Q_DECLARE_METATYPE( QskIcon ) +inline QskIcon::QskIcon( const QString& source ) + : QskIcon( QUrl( source ) ) +{ +} + inline bool QskIcon::isNull() const { if ( m_data->graphic )