6#include "QskComboBox.h"
8#include "QskLabelData.h"
10#include "QskTextOptions.h"
14#include <qquickwindow.h>
24static inline
void qskTraverseOptions(
QskComboBox* comboBox,
int steps )
26 const auto count = comboBox->count();
30 const int index = comboBox->currentIndex();
32 if ( index == -1 && steps < 0 )
35 int nextIndex = ( index + steps ) % count;
39 if ( nextIndex != index )
40 comboBox->setCurrentIndex( nextIndex );
43static inline int qskFindOption(
QskComboBox* comboBox,
const QString& key )
47 const int currentIndex = comboBox->currentIndex();
48 const int count = comboBox->count();
50 for (
int i = 1; i < count; i++ )
52 const int index = ( currentIndex + i ) % count;
53 const auto text = comboBox->textAt( index );
55 if ( text.startsWith( key ) )
63class QskComboBox::PrivateData
66 QPointer < QskMenu > menu;
68 QVector< QskLabelData > options;
69 QString placeholderText;
71 int currentIndex = -1;
74QskComboBox::QskComboBox( QQuickItem* parent )
76 , m_data( new PrivateData() )
78 initSizePolicy( QskSizePolicy::Minimum, QskSizePolicy::Fixed );
80 setPolishOnResize(
true );
82 setAcceptedMouseButtons( Qt::LeftButton );
83 setWheelEnabled(
true );
84 setFocusPolicy( Qt::StrongFocus );
86 setAcceptHoverEvents(
true );
89QskComboBox::~QskComboBox()
93bool QskComboBox::isPressed()
const
95 return hasSkinState( Pressed );
98void QskComboBox::setPressed(
bool on )
100 if ( on == isPressed() )
104 Q_EMIT pressedChanged( on );
112void QskComboBox::setPopupOpen(
bool on )
114 if ( on == isPopupOpen() )
118 if ( on && window() ==
nullptr )
121 qWarning() <<
"QskComboBox can't be opened before being added to a scene.";
134bool QskComboBox::isPopupOpen()
const
136 return hasSkinState( PopupOpen );
139void QskComboBox::setTextOptions(
const QskTextOptions& textOptions )
141 setTextOptionsHint( Text, textOptions );
146 return textOptionsHint( Text );
149int QskComboBox::addOption(
const QString& graphicSource,
const QString& text )
154int QskComboBox::addOption(
const QUrl& graphicSource,
const QString& text )
161 m_data->options += option;
166 if ( isComponentComplete() )
167 Q_EMIT optionsChanged();
172void QskComboBox::setOptions(
const QStringList& options )
174 setOptions( qskCreateLabelData( options ) );
177void QskComboBox::setOptions(
const QVector< QskLabelData >& options )
179 if ( options == m_data->options )
182 m_data->options = options;
183 m_data->currentIndex = -1;
188 Q_EMIT optionsChanged();
191QVector< QskLabelData > QskComboBox::options()
const
193 return m_data->options;
198 return m_data->options.value( index );
201QString QskComboBox::placeholderText()
const
203 return m_data->placeholderText;
206void QskComboBox::setPlaceholderText(
const QString& text )
208 if ( m_data->placeholderText == text )
211 m_data->placeholderText = text;
214 if ( m_data->currentIndex < 0 )
217 Q_EMIT placeholderTextChanged( text );
220QString QskComboBox::textAt(
int index )
const
222 return optionAt( index ).text();
225QString QskComboBox::currentText()
const
227 if( m_data->currentIndex >= 0 && m_data->currentIndex < m_data->options.count() )
228 return m_data->options[ m_data->currentIndex ].text();
230 return m_data->placeholderText;
233void QskComboBox::openPopup()
248 menu->setWrapping(
false );
249 menu->setOrigin( mapToScene( cr.bottomLeft() ) );
250 menu->setFixedWidth( cr.width() );
252 menu->setOptions( m_data->options );
253 menu->setCurrentIndex( currentIndex() );
255 menu->setParent(
this );
256 menu->setParentItem( window()->contentItem() );
257 menu->setPopupFlag( QskPopup::DeleteOnClose,
true );
259 connect( menu, &QskMenu::currentIndexChanged,
260 this, &QskComboBox::indexInPopupChanged );
262 connect( menu, &QskMenu::triggered,
263 this, &QskComboBox::setCurrentIndex );
265 connect( menu, &QskMenu::closed,
this,
266 [
this ]() { setPopupOpen(
false ); setFocus(
true ); } );
272void QskComboBox::closePopup()
275 m_data->menu->close();
278void QskComboBox::mousePressEvent( QMouseEvent* )
281 setPopupOpen(
true );
284void QskComboBox::mouseReleaseEvent( QMouseEvent* )
289void QskComboBox::keyPressEvent( QKeyEvent* event )
291 if ( qskIsButtonPressKey( event ) )
293 if ( !event->isAutoRepeat() )
296 setPopupOpen(
true );
301 switch( event->key() )
308 setPopupOpen(
true );
315 qskTraverseOptions(
this, -1 );
319 case Qt::Key_PageDown:
321 qskTraverseOptions(
this, 1 );
327 setCurrentIndex( 0 );
333 setCurrentIndex( count() - 1 );
339 const int index = qskFindOption(
this, event->text() );
342 setCurrentIndex( index );
348 Inherited::keyPressEvent( event );
351void QskComboBox::keyReleaseEvent( QKeyEvent* event )
353 Inherited::keyReleaseEvent( event );
356void QskComboBox::wheelEvent( QWheelEvent* event )
362#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
363 auto wheelEvent =
new QWheelEvent(
364 event->position(), event->globalPosition(),
365 event->pixelDelta(), event->angleDelta(),
366 event->buttons(), event->modifiers(),
367 event->phase(), event->inverted(), event->source() );
369 auto wheelEvent =
event->clone();
371 QCoreApplication::postEvent( m_data->menu, wheelEvent );
376 const auto steps = -qRound( qskWheelSteps( event ) );
377 qskTraverseOptions(
this, steps );
381void QskComboBox::clear()
383 if ( !m_data->options.isEmpty() )
385 m_data->options.clear();
387 Q_EMIT optionsChanged();
389 if ( m_data->currentIndex >= 0 )
391 m_data->currentIndex = -1;
392 Q_EMIT currentIndexChanged( m_data->currentIndex );
399void QskComboBox::setCurrentIndex(
int index )
401 if ( m_data->currentIndex != index )
403 m_data->currentIndex = index;
406 Q_EMIT currentIndexChanged( index );
410int QskComboBox::currentIndex()
const
412 return m_data->currentIndex;
415int QskComboBox::count()
const
417 return m_data->options.count();
420int QskComboBox::indexInPopup()
const
423 return m_data->menu->currentIndex();
428#include "moc_QskComboBox.cpp"
Lookup key for a QskSkinHintTable.
QRectF contentsRect() const
void setSkinStateFlag(QskAspect::State, bool on=true)