QskComboBox using QskLabelData now

This commit is contained in:
Uwe Rathmann 2023-03-09 17:59:54 +01:00
parent f9f5de8eb0
commit e36f81b297
8 changed files with 85 additions and 124 deletions

View File

@ -7,6 +7,7 @@
#include <QskComboBox.h>
#include <QskSegmentedBar.h>
#include <QskLabelData.h>
namespace
{

View File

@ -20,6 +20,11 @@ static void qskRegisterLabelData()
Q_CONSTRUCTOR_FUNCTION( qskRegisterLabelData )
QskLabelData::QskLabelData( const char* text )
: m_text( text )
{
}
QskLabelData::QskLabelData( const QString& text )
: m_text( text )
{

View File

@ -23,6 +23,7 @@ class QSK_EXPORT QskLabelData
public:
QskLabelData() = default;
QskLabelData( const char* );
QskLabelData( const QString& );
QskLabelData( const QskIcon& );
QskLabelData( const QString&, const QskIcon& );

View File

@ -5,8 +5,7 @@
#include "QskComboBox.h"
#include "QskGraphicProvider.h"
#include "QskGraphic.h"
#include "QskLabelData.h"
#include "QskMenu.h"
#include "QskTextOptions.h"
#include "QskEvent.h"
@ -60,41 +59,12 @@ static inline int qskFindOption( QskComboBox* comboBox, const QString& key )
return -1;
}
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
{
public:
QPointer < QskMenu > menu;
QVector< Option > options;
QVector< QskLabelData > options;
QString placeholderText;
int currentIndex = -1;
@ -113,7 +83,6 @@ QskComboBox::QskComboBox( QQuickItem* parent )
setFocusPolicy( Qt::StrongFocus );
setAcceptHoverEvents( true );
}
QskComboBox::~QskComboBox()
@ -138,17 +107,6 @@ bool QskComboBox::isPopupOpen() const
return hasSkinState( PopupOpen );
}
QskGraphic QskComboBox::icon() const
{
if( m_data->currentIndex >= 0 )
{
const auto option = optionAt( m_data->currentIndex );
return option.at( 0 ).value< QskGraphic >();
}
return QskGraphic();
}
void QskComboBox::setTextOptions( const QskTextOptions& textOptions )
{
setTextOptionsHint( Text, textOptions );
@ -159,52 +117,51 @@ QskTextOptions QskComboBox::textOptions() const
return textOptionsHint( Text );
}
void QskComboBox::addOption( const QString& text )
int QskComboBox::addOption( const QString& graphicSource, const QString& text )
{
addOption( QUrl(), text );
return addOption( QskLabelData( text, QskIcon( graphicSource ) ) );
}
void QskComboBox::addOption( const QskGraphic& graphic, const QString& text )
int QskComboBox::addOption( const QUrl& graphicSource, const QString& text )
{
m_data->options += Option( graphic, text );
return addOption( QskLabelData( text, QskIcon( graphicSource ) ) );
}
int QskComboBox::addOption( const QskLabelData& option )
{
m_data->options += option;
resetImplicitSize();
update();
if ( isComponentComplete() )
Q_EMIT countChanged( count() );
Q_EMIT optionsChanged();
return count() - 1;
}
void QskComboBox::addOption( const QString& graphicSource, const QString& text )
void QskComboBox::setOptions( const QVector< QskLabelData >& options )
{
addOption( QUrl( graphicSource ), text );
}
if ( options == m_data->options )
return;
void QskComboBox::addOption( const QUrl& graphicSource, const QString& text )
{
m_data->options += Option( graphicSource, text );
m_data->options = options;
m_data->currentIndex = -1; // currentIndexChanged ???
resetImplicitSize();
update();
if ( isComponentComplete() )
Q_EMIT countChanged( count() );
Q_EMIT optionsChanged();
}
QVariantList QskComboBox::optionAt( int index ) const
QVector< QskLabelData > QskComboBox::options() const
{
const auto& options = m_data->options;
return 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;
QskLabelData QskComboBox::optionAt( int index ) const
{
return m_data->options.value( index );
}
QString QskComboBox::placeholderText() const
@ -228,16 +185,13 @@ void QskComboBox::setPlaceholderText( const QString& text )
QString QskComboBox::textAt( int index ) const
{
if ( index >= 0 && index < m_data->options.count() )
return m_data->options[ index ].text;
return QString();
return optionAt( index ).text();
}
QString QskComboBox::currentText() const
{
if( m_data->currentIndex >= 0 )
return m_data->options[ m_data->currentIndex ].text;
if( m_data->currentIndex >= 0 && m_data->currentIndex < m_data->options.count() )
return m_data->options[ m_data->currentIndex ].text();
return m_data->placeholderText;
}
@ -265,7 +219,7 @@ void QskComboBox::openPopup()
menu->setFixedWidth( cr.width() );
for ( const auto& option : m_data->options )
menu->addOption( option.graphic, option.text );
menu->addOption( option.icon().graphic(), option.text() );
connect( menu, &QskMenu::currentIndexChanged,
this, &QskComboBox::indexInPopupChanged );
@ -391,8 +345,15 @@ void QskComboBox::clear()
{
m_data->options.clear();
if ( isComponentComplete() )
Q_EMIT countChanged( count() );
Q_EMIT optionsChanged();
if ( m_data->currentIndex >= 0 )
{
m_data->currentIndex = -1;
Q_EMIT currentIndexChanged( m_data->currentIndex );
}
update();
}
}

View File

@ -8,19 +8,22 @@
#include "QskControl.h"
class QskGraphic;
class QskLabelData;
class QSK_EXPORT QskComboBox : public QskControl
{
Q_OBJECT
Q_PROPERTY( QVector< QskLabelData > options READ options
WRITE setOptions NOTIFY optionsChanged )
Q_PROPERTY( int currentIndex READ currentIndex
WRITE setCurrentIndex NOTIFY currentIndexChanged )
Q_PROPERTY( QString currentText READ currentText
NOTIFY currentIndexChanged )
Q_PROPERTY( int count READ count NOTIFY countChanged )
Q_PROPERTY( int count READ count )
Q_PROPERTY( QString placeholderText READ placeholderText
WRITE setPlaceholderText NOTIFY placeholderTextChanged )
@ -41,15 +44,17 @@ class QSK_EXPORT QskComboBox : public QskControl
void setPopupOpen( bool );
bool isPopupOpen() const;
QskGraphic icon() const;
void setTextOptions( const QskTextOptions& );
QskTextOptions textOptions() const;
void addOption( const QString& text );
void addOption( const QUrl& iconSource, const QString& text );
void addOption( const QString& iconSource, const QString& text );
void addOption( const QskGraphic&, const QString& text );
int addOption( const QUrl&, const QString& );
int addOption( const QString&, const QString& );
int addOption( const QskLabelData& );
void setOptions( const QVector< QskLabelData >& );
QVector< QskLabelData > options() const;
QskLabelData optionAt( int ) const;
void clear();
@ -60,7 +65,6 @@ class QSK_EXPORT QskComboBox : public QskControl
virtual int indexInPopup() const;
int count() const;
QVariantList optionAt( int ) const;
QString textAt( int ) const;
QString placeholderText() const;
@ -73,7 +77,7 @@ class QSK_EXPORT QskComboBox : public QskControl
void currentIndexChanged( int );
void indexInPopupChanged( int );
void countChanged( int );
void optionsChanged();
void placeholderTextChanged( const QString& );
protected:

View File

@ -7,43 +7,13 @@
#include "QskComboBox.h"
#include "QskGraphic.h"
#include "QskLabelData.h"
#include "QskSGNode.h"
#include "QskSubcontrolLayoutEngine.h"
namespace
{
#if 1 // unify with the implementation from QskMenu
template< class T >
static inline QVariant qskSampleAt( const QskComboBox* box )
{
if( std::is_same< T, QString >() )
{
return box->currentText();
}
const int index = box->currentIndex();
if( index < 0 )
return QVariant::fromValue( T() );
const auto list = box->optionAt( index );
for ( const auto& value : list )
{
if ( value.canConvert< T >() )
return value;
}
return QVariant();
}
template< class T >
static inline T qskValueAt( const QskComboBox* box )
{
const auto sample = qskSampleAt< T >( box );
return sample.template value< T >();
}
#endif
class LayoutEngine : public QskSubcontrolLayoutEngine
{
public:
@ -52,12 +22,27 @@ namespace
{
setSpacing( box->spacingHint( QskComboBox::Panel ) );
QSizeF graphicSize;
QString text;
if ( box->currentIndex() >= 0 )
{
const auto option = box->optionAt( box->currentIndex() );
graphicSize = option.icon().graphic().defaultSize();
text = option.text();
}
else
{
text = box->placeholderText();
}
setGraphicTextElements( box,
QskComboBox::Text, qskValueAt< QString >( box ),
QskComboBox::Icon, qskValueAt< QskGraphic >( box ).defaultSize() );
QskComboBox::Text, text, QskComboBox::Icon, graphicSize );
const auto alignment = box->alignmentHint(
QskComboBox::Panel, Qt::AlignLeft );
setFixedContent( QskComboBox::Text, Qt::Horizontal, alignment );
}
};
@ -115,7 +100,11 @@ QSGNode* QskComboBoxSkinlet::updateSubNode(
return updateBoxNode( box, node, Q::Panel );
case IconRole:
return updateGraphicNode( box, node, box->icon(), Q::Icon );
{
const auto option = box->optionAt( box->currentIndex() );
return updateGraphicNode( box, node,
option.icon().graphic(), Q::Icon );
}
case TextRole:
return updateTextNode( box, node );

View File

@ -131,6 +131,7 @@ void QskSegmentedBar::setOptions( const QVector< QskLabelData >& options )
resetImplicitSize();
update();
// selectedIndex ???
Q_EMIT optionsChanged();
}

View File

@ -12,7 +12,6 @@
#include <qstring.h>
class QskTextOptions;
class QskGraphic;
class QskLabelData;
class QSK_EXPORT QskSegmentedBar : public QskControl