qskinny/src/controls/QskComboBox.cpp
Peter Hartmann a89d3def3b Add new control QskComboBox
Resolves #102
2023-02-17 17:26:06 +01:00

277 lines
5.5 KiB
C++

/******************************************************************************
* QSkinny - Copyright (C) 2023 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#include "QskComboBox.h"
#include "QskGraphic.h"
#include "QskMenu.h"
#include "QskTextOptions.h"
#include <QGuiApplication>
QSK_SUBCONTROL( QskComboBox, Panel )
QSK_SUBCONTROL( QskComboBox, Graphic )
QSK_SUBCONTROL( QskComboBox, Text )
QSK_SUBCONTROL( QskComboBox, OpenMenuGraphic )
QSK_SUBCONTROL( QskComboBox, Ripple )
QSK_SYSTEM_STATE( QskComboBox, Pressed, QskAspect::FirstSystemState << 1 )
QSK_SYSTEM_STATE( QskComboBox, PopupOpen, QskAspect::FirstSystemState << 2 )
class QskComboBox::PrivateData
{
public:
PrivateData( QskComboBox* const box )
: menu( new QskMenu( box ) )
{
menu->setPopupFlag( QskPopup::DeleteOnClose, false );
}
QskMenu* const menu;
QString label;
};
QskComboBox::QskComboBox( QQuickItem* parent )
: Inherited( parent )
, m_data( new PrivateData( this ) )
{
initSizePolicy( QskSizePolicy::Minimum, QskSizePolicy::Fixed );
setPolishOnResize( true );
setAcceptedMouseButtons( Qt::LeftButton );
setWheelEnabled( true );
setFocusPolicy( Qt::StrongFocus );
setAcceptHoverEvents( true );
connect( m_data->menu, &QskMenu::currentIndexChanged, this, &QskComboBox::currentIndexChanged );
connect( m_data->menu, &QskMenu::currentIndexChanged, this, &QQuickItem::update );
connect( m_data->menu, &QskMenu::countChanged, this, &QskComboBox::countChanged );
connect( this, &QskComboBox::currentIndexChanged,
this, &QskControl::focusIndicatorRectChanged );
connect( m_data->menu, &QskMenu::closed, this, [ this ]()
{
setPopupOpen( false );
setFocus( true );
} );
connect( this, &QskComboBox::pressed, this, &QskComboBox::togglePopup );
}
QskComboBox::~QskComboBox()
{
}
void QskComboBox::setPressed( bool on )
{
if ( on == isPressed() )
return;
setSkinStateFlag( Pressed, on );
Q_EMIT pressedChanged( on );
if ( on )
Q_EMIT pressed();
else
Q_EMIT released();
}
bool QskComboBox::isPressed() const
{
return hasSkinState( Pressed );
}
void QskComboBox::setPopupOpen( bool on )
{
if ( on == isPopupOpen() )
return;
if( on )
{
openPopup();
}
else
{
closePopup();
}
setSkinStateFlag( PopupOpen, on );
Q_EMIT popupOpenChanged( on );
}
bool QskComboBox::isPopupOpen() const
{
return hasSkinState( PopupOpen );
}
QskGraphic QskComboBox::graphic() const
{
const int index = m_data->menu->currentIndex();
if( index >= 0 )
{
const auto option = m_data->menu->optionAt( index );
return option.at( 0 ).value< QskGraphic >();
}
else
{
return {};
}
}
void QskComboBox::setTextOptions( const QskTextOptions& textOptions )
{
setTextOptionsHint( Text, textOptions );
}
QskTextOptions QskComboBox::textOptions() const
{
return textOptionsHint( Text );
}
void QskComboBox::addOption( const QUrl& graphicSource, const QString& text )
{
m_data->menu->addOption( graphicSource, text );
}
QVariantList QskComboBox::optionAt( int index ) const
{
return m_data->menu->optionAt( index );
}
QString QskComboBox::label() const
{
return m_data->label;
}
void QskComboBox::setLabel( const QString& label )
{
m_data->label = label;
}
QString QskComboBox::text() const
{
const int index = m_data->menu->currentIndex();
if( index >= 0 )
{
const auto option = m_data->menu->optionAt( index );
return option.at( 1 ).toString();
}
else
{
return label();
}
}
void QskComboBox::togglePopup()
{
setPopupOpen( !isPopupOpen() );
}
void QskComboBox::openPopup()
{
m_data->menu->open();
}
void QskComboBox::closePopup()
{
m_data->menu->close();
}
void QskComboBox::updateLayout()
{
Inherited::updateLayout();
auto origin = contentsRect().bottomLeft();
m_data->menu->setOrigin( origin );
m_data->menu->setFixedWidth( contentsRect().width() );
}
void QskComboBox::mousePressEvent( QMouseEvent* event )
{
Q_UNUSED( event )
setPressed( true );
}
void QskComboBox::mouseReleaseEvent( QMouseEvent* event )
{
Q_UNUSED( event )
releaseButton();
}
void QskComboBox::keyPressEvent( QKeyEvent* event )
{
switch ( event->key() )
{
case Qt::Key_Select:
case Qt::Key_Space:
{
if ( !event->isAutoRepeat() )
{
setPressed( true );
// calling release button here, because
// we will never get the key release event
// when the menu is opened:
releaseButton();
}
// always accepting
return;
}
}
Inherited::keyPressEvent( event );
}
void QskComboBox::keyReleaseEvent( QKeyEvent* event )
{
Inherited::keyReleaseEvent( event );
}
void QskComboBox::clear()
{
m_data->menu->clear();
update();
}
void QskComboBox::click()
{
setPressed( true );
releaseButton();
}
void QskComboBox::setCurrentIndex( int index )
{
m_data->menu->setCurrentIndex( index );
}
int QskComboBox::currentIndex() const
{
return m_data->menu->currentIndex();
}
int QskComboBox::count() const
{
return m_data->menu->count();
}
void QskComboBox::releaseButton()
{
if ( !isPressed() )
return;
setPressed( false );
Q_EMIT clicked();
}
#include "moc_QskComboBox.cpp"