QskComboBox is creating its menu only temporary now

This commit is contained in:
Uwe Rathmann 2023-03-07 13:26:36 +01:00
parent 69546707d2
commit fa998a9496
3 changed files with 126 additions and 47 deletions

View File

@ -73,16 +73,16 @@ void SelectorPage::populate()
auto* comboBox1 = new QskComboBox( comboBoxBox ); auto* comboBox1 = new QskComboBox( comboBoxBox );
comboBox1->setPlaceholderText( "< options >" ); comboBox1->setPlaceholderText( "< options >" );
comboBox1->addOption( {}, "airport" ); comboBox1->addOption( "airport" );
comboBox1->addOption( {}, "flight" ); comboBox1->addOption( "flight" );
comboBox1->addOption( {}, "pizza" ); comboBox1->addOption( "pizza" );
comboBox1->addOption( {}, "soccer" ); comboBox1->addOption( "soccer" );
auto* comboBox2 = new QskComboBox( comboBoxBox ); auto* comboBox2 = new QskComboBox( comboBoxBox );
comboBox2->addOption( { "airport_shuttle" }, "airport" ); comboBox2->addOption( "airport_shuttle", "airport" );
comboBox2->addOption( { "flight" }, "flight" ); comboBox2->addOption( "flight", "flight" );
comboBox2->addOption( { "local_pizza" }, "pizza" ); comboBox2->addOption( "local_pizza", "pizza" );
comboBox2->addOption( { "sports_soccer" }, "soccer" ); comboBox2->addOption( "sports_soccer", "soccer" );
comboBox2->setCurrentIndex( 2 ); comboBox2->setCurrentIndex( 2 );
setStretchFactor( 0, 0 ); setStretchFactor( 0, 0 );

View File

@ -5,11 +5,13 @@
#include "QskComboBox.h" #include "QskComboBox.h"
#include "QskGraphicProvider.h"
#include "QskGraphic.h" #include "QskGraphic.h"
#include "QskMenu.h" #include "QskMenu.h"
#include "QskTextOptions.h" #include "QskTextOptions.h"
#include "QskEvent.h" #include "QskEvent.h"
#include <qpointer.h>
#include <qquickwindow.h> #include <qquickwindow.h>
QSK_SUBCONTROL( QskComboBox, Panel ) QSK_SUBCONTROL( QskComboBox, Panel )
@ -19,7 +21,7 @@ QSK_SUBCONTROL( QskComboBox, PopupIndicator )
QSK_SYSTEM_STATE( QskComboBox, PopupOpen, QskAspect::FirstSystemState << 1 ) QSK_SYSTEM_STATE( QskComboBox, PopupOpen, QskAspect::FirstSystemState << 1 )
static inline void qskIncrement( QskComboBox* comboBox, int steps ) static inline void qskTraverseOptions( QskComboBox* comboBox, int steps )
{ {
const auto count = comboBox->count(); const auto count = comboBox->count();
if ( count == 0 ) if ( count == 0 )
@ -33,29 +35,46 @@ static inline void qskIncrement( QskComboBox* comboBox, int steps )
int nextIndex = ( index + steps ) % count; int nextIndex = ( index + steps ) % count;
if ( nextIndex < 0 ) if ( nextIndex < 0 )
nextIndex += count; nextIndex += count;
if ( nextIndex != index ) if ( nextIndex != index )
comboBox->setCurrentIndex( nextIndex ); comboBox->setCurrentIndex( nextIndex );
}
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;
};
} }
class QskComboBox::PrivateData class QskComboBox::PrivateData
{ {
public: public:
PrivateData( QskComboBox* comboBox ) QPointer < QskPopup > menu;
{
menu = new QskMenu();
/* QVector< Option > options;
The popup menu is supposed to be modal for the window and
therefore needs the root item of the window as parent item.
So we set the box as QObject parent only, so that it gets
destroyed properly.
*/
menu->setParent( comboBox );
menu->setPopupFlag( QskPopup::DeleteOnClose, false );
}
QskMenu* menu;
QString placeholderText; QString placeholderText;
int currentIndex = -1; int currentIndex = -1;
@ -63,7 +82,7 @@ class QskComboBox::PrivateData
QskComboBox::QskComboBox( QQuickItem* parent ) QskComboBox::QskComboBox( QQuickItem* parent )
: Inherited( parent ) : Inherited( parent )
, m_data( new PrivateData( this ) ) , m_data( new PrivateData() )
{ {
initSizePolicy( QskSizePolicy::Minimum, QskSizePolicy::Fixed ); initSizePolicy( QskSizePolicy::Minimum, QskSizePolicy::Fixed );
@ -75,14 +94,6 @@ QskComboBox::QskComboBox( QQuickItem* parent )
setAcceptHoverEvents( true ); setAcceptHoverEvents( true );
connect( m_data->menu, &QskMenu::triggered,
this, &QskComboBox::setCurrentIndex );
connect( m_data->menu, &QskMenu::countChanged,
this, &QskComboBox::countChanged );
connect( m_data->menu, &QskMenu::closed, this,
[ this ]() { setPopupOpen( false ); setFocus( true ); } );
} }
QskComboBox::~QskComboBox() QskComboBox::~QskComboBox()
@ -128,14 +139,52 @@ QskTextOptions QskComboBox::textOptions() const
return textOptionsHint( Text ); return textOptionsHint( Text );
} }
void QskComboBox::addOption( const QString& text )
{
addOption( QUrl(), text );
}
void QskComboBox::addOption( const QskGraphic& graphic, const QString& text )
{
m_data->options += Option( graphic, text );
resetImplicitSize();
update();
if ( isComponentComplete() )
Q_EMIT countChanged( count() );
}
void QskComboBox::addOption( const QString& graphicSource, const QString& text )
{
addOption( QUrl( graphicSource ), text );
}
void QskComboBox::addOption( const QUrl& graphicSource, const QString& text ) void QskComboBox::addOption( const QUrl& graphicSource, const QString& text )
{ {
m_data->menu->addOption( graphicSource, text ); m_data->options += Option( graphicSource, text );
resetImplicitSize();
update();
if ( isComponentComplete() )
Q_EMIT countChanged( count() );
} }
QVariantList QskComboBox::optionAt( int index ) const QVariantList QskComboBox::optionAt( int index ) const
{ {
return m_data->menu->optionAt( index ); 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 QskComboBox::placeholderText() const QString QskComboBox::placeholderText() const
@ -170,20 +219,37 @@ QString QskComboBox::currentText() const
void QskComboBox::openPopup() void QskComboBox::openPopup()
{ {
if ( m_data->menu )
return;
const auto cr = contentsRect(); const auto cr = contentsRect();
auto menu = m_data->menu; auto menu = new QskMenu();
menu->setParent( this );
menu->setParentItem( window()->contentItem() ); menu->setParentItem( window()->contentItem() );
menu->setPopupFlag( QskPopup::DeleteOnClose, true );
menu->setOrigin( mapToScene( cr.bottomLeft() ) ); menu->setOrigin( mapToScene( cr.bottomLeft() ) );
menu->setFixedWidth( cr.width() ); menu->setFixedWidth( cr.width() );
for ( const auto& option : m_data->options )
menu->addOption( option.graphic, option.text );
connect( menu, &QskMenu::triggered,
this, &QskComboBox::setCurrentIndex );
connect( menu, &QskMenu::closed, this,
[ this ]() { setPopupOpen( false ); setFocus( true ); } );
m_data->menu = menu;
menu->open(); menu->open();
} }
void QskComboBox::closePopup() void QskComboBox::closePopup()
{ {
m_data->menu->close(); if ( m_data->menu )
m_data->menu->close();
} }
void QskComboBox::mousePressEvent( QMouseEvent* ) void QskComboBox::mousePressEvent( QMouseEvent* )
@ -219,13 +285,13 @@ void QskComboBox::keyPressEvent( QKeyEvent* event )
case Qt::Key_Up: case Qt::Key_Up:
case Qt::Key_PageUp: case Qt::Key_PageUp:
{ {
qskIncrement( this, -1 ); qskTraverseOptions( this, -1 );
return; return;
} }
case Qt::Key_Down: case Qt::Key_Down:
case Qt::Key_PageDown: case Qt::Key_PageDown:
{ {
qskIncrement( this, 1 ); qskTraverseOptions( this, 1 );
return; return;
} }
case Qt::Key_Home: case Qt::Key_Home:
@ -256,17 +322,27 @@ void QskComboBox::keyReleaseEvent( QKeyEvent* event )
void QskComboBox::wheelEvent( QWheelEvent* event ) void QskComboBox::wheelEvent( QWheelEvent* event )
{ {
if ( !isPopupOpen() ) if ( isPopupOpen() )
{
if ( m_data->menu )
QCoreApplication::postEvent( m_data->menu, event->clone() );
}
else
{ {
const auto steps = -qRound( qskWheelSteps( event ) ); const auto steps = -qRound( qskWheelSteps( event ) );
qskIncrement( this, steps ); qskTraverseOptions( this, steps );
} }
} }
void QskComboBox::clear() void QskComboBox::clear()
{ {
m_data->menu->clear(); if ( !m_data->options.isEmpty() )
setCurrentIndex( -1 ); {
m_data->options.clear();
if ( isComponentComplete() )
Q_EMIT countChanged( count() );
}
} }
void QskComboBox::setCurrentIndex( int index ) void QskComboBox::setCurrentIndex( int index )
@ -287,7 +363,7 @@ int QskComboBox::currentIndex() const
int QskComboBox::count() const int QskComboBox::count() const
{ {
return m_data->menu->count(); return m_data->options.count();
} }
#include "moc_QskComboBox.cpp" #include "moc_QskComboBox.cpp"

View File

@ -42,7 +42,10 @@ class QSK_EXPORT QskComboBox : public QskControl
void setTextOptions( const QskTextOptions& ); void setTextOptions( const QskTextOptions& );
QskTextOptions textOptions() const; QskTextOptions textOptions() const;
void addOption( const QUrl&, const QString& ); void addOption( const QString& text );
void addOption( const QUrl& graphicSource, const QString& text );
void addOption( const QString& graphicSource, const QString& text );
void addOption( const QskGraphic&, const QString& text );
void clear(); void clear();
@ -61,7 +64,7 @@ class QSK_EXPORT QskComboBox : public QskControl
Q_SIGNALS: Q_SIGNALS:
void currentIndexChanged( int ); void currentIndexChanged( int );
void countChanged(); void countChanged( int );
void placeholderTextChanged( const QString& ); void placeholderTextChanged( const QString& );
protected: protected: