2022-04-20 14:20:41 +02:00
|
|
|
/******************************************************************************
|
2024-01-17 14:31:45 +01:00
|
|
|
* QSkinny - Copyright (C) The authors
|
2023-04-06 09:23:37 +02:00
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
2022-04-20 14:20:41 +02:00
|
|
|
*****************************************************************************/
|
|
|
|
|
2021-12-23 18:36:32 +01:00
|
|
|
#include "QskMenu.h"
|
|
|
|
|
2022-04-20 14:20:41 +02:00
|
|
|
#include "QskGraphicProvider.h"
|
2023-03-10 09:18:52 +01:00
|
|
|
#include "QskLabelData.h"
|
2022-04-20 14:20:41 +02:00
|
|
|
#include "QskTextOptions.h"
|
|
|
|
#include "QskGraphic.h"
|
|
|
|
#include "QskColorFilter.h"
|
|
|
|
#include "QskSkinlet.h"
|
|
|
|
#include "QskEvent.h"
|
|
|
|
#include "QskPlatform.h"
|
2021-12-23 18:36:32 +01:00
|
|
|
|
2021-12-24 16:20:34 +01:00
|
|
|
#include <qvector.h>
|
2021-12-27 09:50:14 +01:00
|
|
|
#include <qvariant.h>
|
2021-12-30 11:13:48 +01:00
|
|
|
#include <qeventloop.h>
|
2021-12-23 18:36:32 +01:00
|
|
|
|
2023-11-03 18:13:24 +01:00
|
|
|
QSK_QT_PRIVATE_BEGIN
|
|
|
|
#include <private/qquickitem_p.h>
|
|
|
|
QSK_QT_PRIVATE_END
|
|
|
|
|
2021-12-23 18:36:32 +01:00
|
|
|
QSK_SUBCONTROL( QskMenu, Panel )
|
2022-04-20 13:58:53 +02:00
|
|
|
QSK_SUBCONTROL( QskMenu, Segment )
|
2021-12-24 16:20:34 +01:00
|
|
|
QSK_SUBCONTROL( QskMenu, Cursor )
|
2021-12-23 18:36:32 +01:00
|
|
|
QSK_SUBCONTROL( QskMenu, Text )
|
2023-03-08 14:11:27 +01:00
|
|
|
QSK_SUBCONTROL( QskMenu, Icon )
|
2022-01-06 18:36:15 +01:00
|
|
|
QSK_SUBCONTROL( QskMenu, Separator )
|
2021-12-23 18:36:32 +01:00
|
|
|
|
|
|
|
QSK_SYSTEM_STATE( QskMenu, Selected, QskAspect::FirstSystemState << 2 )
|
2023-06-30 15:44:49 +02:00
|
|
|
QSK_SYSTEM_STATE( QskMenu, Pressed, QskAspect::FirstSystemState << 3 )
|
2021-12-23 18:36:32 +01:00
|
|
|
|
2023-05-16 12:49:46 +02:00
|
|
|
static inline int qskActionIndex( const QVector< int >& actions, int index )
|
|
|
|
{
|
|
|
|
if ( index < 0 )
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
auto it = std::lower_bound( actions.constBegin(), actions.constEnd(), index );
|
|
|
|
return it - actions.constBegin();
|
|
|
|
}
|
|
|
|
|
2021-12-23 18:36:32 +01:00
|
|
|
class QskMenu::PrivateData
|
|
|
|
{
|
2021-12-23 19:05:59 +01:00
|
|
|
public:
|
2023-03-10 09:18:52 +01:00
|
|
|
QPointF origin;
|
|
|
|
|
|
|
|
QVector< QskLabelData > options;
|
2023-05-16 12:49:46 +02:00
|
|
|
|
2022-01-06 18:36:15 +01:00
|
|
|
QVector< int > separators;
|
2023-05-16 12:49:46 +02:00
|
|
|
QVector< int > actions;
|
2021-12-23 18:36:32 +01:00
|
|
|
|
2023-03-10 12:46:19 +01:00
|
|
|
int triggeredIndex = -1;
|
2021-12-29 16:23:19 +01:00
|
|
|
int currentIndex = -1;
|
2021-12-23 19:05:59 +01:00
|
|
|
bool isPressed = false;
|
2021-12-23 18:36:32 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
QskMenu::QskMenu( QQuickItem* parent )
|
|
|
|
: Inherited( parent )
|
|
|
|
, m_data( new PrivateData )
|
|
|
|
{
|
2023-11-28 15:39:20 +01:00
|
|
|
#if 1
|
|
|
|
/*
|
|
|
|
The overlay is clipped from the drop down fading effect.
|
|
|
|
Until it is fixed we simply disable it. TODO ...
|
|
|
|
*/
|
|
|
|
setOverlay( false );
|
|
|
|
#endif
|
2021-12-23 18:36:32 +01:00
|
|
|
setModal( true );
|
|
|
|
|
|
|
|
setPopupFlag( QskPopup::CloseOnPressOutside, true );
|
|
|
|
setPopupFlag( QskPopup::DeleteOnClose, true );
|
|
|
|
|
2023-11-03 18:13:24 +01:00
|
|
|
setPlacementPolicy( QskPlacementPolicy::Ignore );
|
2023-02-14 17:33:13 +01:00
|
|
|
setSubcontrolProxy( Inherited::Overlay, Overlay );
|
|
|
|
|
2021-12-23 18:36:32 +01:00
|
|
|
initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
|
2023-03-06 16:37:28 +01:00
|
|
|
|
2023-10-19 09:47:42 +02:00
|
|
|
// we hide the focus indicator while sliding
|
2023-11-03 18:13:24 +01:00
|
|
|
connect( this, &QskPopup::fadingChanged,
|
|
|
|
this, &QskControl::focusIndicatorRectChanged );
|
|
|
|
|
|
|
|
connect( this, &QskPopup::fadingChanged,
|
|
|
|
this, &QQuickItem::setClip );
|
2023-03-10 12:46:19 +01:00
|
|
|
|
2023-11-03 18:13:24 +01:00
|
|
|
connect( this, &QskPopup::opened, this,
|
2023-03-10 12:46:19 +01:00
|
|
|
[this]() { m_data->triggeredIndex = -1; } );
|
2023-06-30 15:28:20 +02:00
|
|
|
|
|
|
|
setAcceptHoverEvents( true );
|
2021-12-23 18:36:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
QskMenu::~QskMenu()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2023-11-03 18:13:24 +01:00
|
|
|
QRectF QskMenu::clipRect() const
|
|
|
|
{
|
|
|
|
if ( isFading() )
|
|
|
|
{
|
|
|
|
constexpr qreal d = 1e6;
|
|
|
|
return QRectF( -d, m_data->origin.y() - y(), 2.0 * d, d );
|
|
|
|
}
|
|
|
|
|
|
|
|
return Inherited::clipRect();
|
|
|
|
}
|
|
|
|
|
2022-04-05 10:41:36 +02:00
|
|
|
#if 1
|
|
|
|
|
|
|
|
// has no effect as we do not offer submenus yet. TODO ...
|
2021-12-26 12:17:31 +01:00
|
|
|
bool QskMenu::isCascading() const
|
|
|
|
{
|
2022-04-16 12:25:39 +02:00
|
|
|
return flagHint( QskMenu::Panel | QskAspect::Style, qskMaybeDesktopPlatform() );
|
2021-12-26 12:17:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskMenu::setCascading( bool on )
|
|
|
|
{
|
|
|
|
if ( setFlagHint( QskMenu::Panel | QskAspect::Style, on ) )
|
|
|
|
Q_EMIT cascadingChanged( on );
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskMenu::resetCascading()
|
|
|
|
{
|
2023-03-02 12:19:32 +01:00
|
|
|
if ( resetSkinHint( QskMenu::Panel | QskAspect::Style ) )
|
2021-12-26 12:17:31 +01:00
|
|
|
Q_EMIT cascadingChanged( isCascading() );
|
|
|
|
}
|
|
|
|
|
2022-04-05 10:41:36 +02:00
|
|
|
#endif
|
|
|
|
|
2021-12-23 18:36:32 +01:00
|
|
|
void QskMenu::setOrigin( const QPointF& origin )
|
2021-12-23 19:05:59 +01:00
|
|
|
{
|
2021-12-23 18:36:32 +01:00
|
|
|
if ( origin != m_data->origin )
|
|
|
|
{
|
|
|
|
m_data->origin = origin;
|
|
|
|
Q_EMIT originChanged( origin );
|
|
|
|
}
|
|
|
|
}
|
2021-12-23 19:05:59 +01:00
|
|
|
|
2021-12-23 18:36:32 +01:00
|
|
|
QPointF QskMenu::origin() const
|
|
|
|
{
|
|
|
|
return m_data->origin;
|
|
|
|
}
|
|
|
|
|
2023-03-10 09:18:52 +01:00
|
|
|
void QskMenu::setTextOptions( const QskTextOptions& textOptions )
|
2023-03-07 13:26:05 +01:00
|
|
|
{
|
2023-03-10 09:18:52 +01:00
|
|
|
setTextOptionsHint( Text, textOptions );
|
2023-03-07 13:26:05 +01:00
|
|
|
}
|
|
|
|
|
2023-03-10 09:18:52 +01:00
|
|
|
QskTextOptions QskMenu::textOptions() const
|
2021-12-23 18:36:32 +01:00
|
|
|
{
|
2023-03-10 09:18:52 +01:00
|
|
|
return textOptionsHint( Text );
|
|
|
|
}
|
2021-12-23 18:36:32 +01:00
|
|
|
|
2023-03-10 09:18:52 +01:00
|
|
|
int QskMenu::addOption( const QString& graphicSource, const QString& text )
|
|
|
|
{
|
|
|
|
return addOption( QskLabelData( text, graphicSource ) );
|
|
|
|
}
|
2021-12-27 09:50:14 +01:00
|
|
|
|
2023-03-10 09:18:52 +01:00
|
|
|
int QskMenu::addOption( const QUrl& graphicSource, const QString& text )
|
|
|
|
{
|
|
|
|
return addOption( QskLabelData( text, graphicSource ) );
|
2021-12-23 18:36:32 +01:00
|
|
|
}
|
|
|
|
|
2023-03-10 09:18:52 +01:00
|
|
|
int QskMenu::addOption( const QskLabelData& option )
|
2023-03-07 13:26:05 +01:00
|
|
|
{
|
2023-05-16 12:49:46 +02:00
|
|
|
const int index = m_data->options.count();
|
|
|
|
|
2023-03-10 09:18:52 +01:00
|
|
|
m_data->options += option;
|
2023-03-07 13:26:05 +01:00
|
|
|
|
2023-05-16 12:49:46 +02:00
|
|
|
if ( option.isEmpty() )
|
|
|
|
m_data->separators += index;
|
|
|
|
else
|
|
|
|
m_data->actions += index;
|
|
|
|
|
2023-03-07 13:26:05 +01:00
|
|
|
resetImplicitSize();
|
|
|
|
update();
|
|
|
|
|
|
|
|
if ( isComponentComplete() )
|
2023-03-10 09:18:52 +01:00
|
|
|
Q_EMIT optionsChanged();
|
2023-03-07 13:26:05 +01:00
|
|
|
|
2023-05-16 12:49:46 +02:00
|
|
|
return index;
|
2022-01-06 18:36:15 +01:00
|
|
|
}
|
|
|
|
|
2023-03-10 12:46:19 +01:00
|
|
|
void QskMenu::setOptions( const QStringList& options )
|
|
|
|
{
|
|
|
|
setOptions( qskCreateLabelData( options ) );
|
|
|
|
}
|
|
|
|
|
2023-03-10 09:18:52 +01:00
|
|
|
void QskMenu::setOptions( const QVector< QskLabelData >& options )
|
2022-01-06 18:36:15 +01:00
|
|
|
{
|
2023-03-10 09:18:52 +01:00
|
|
|
m_data->options = options;
|
2021-12-23 18:36:32 +01:00
|
|
|
|
2023-05-16 12:49:46 +02:00
|
|
|
for ( int i = 0; i < options.count(); i++ )
|
|
|
|
{
|
|
|
|
if ( options[i].isEmpty() )
|
|
|
|
m_data->separators += i;
|
|
|
|
else
|
|
|
|
m_data->actions += i;
|
|
|
|
}
|
|
|
|
|
2023-03-10 09:18:52 +01:00
|
|
|
if ( m_data->currentIndex >= 0 )
|
|
|
|
{
|
|
|
|
m_data->currentIndex = -1;
|
|
|
|
|
|
|
|
if ( isComponentComplete() )
|
|
|
|
Q_EMIT currentIndexChanged( m_data->currentIndex );
|
|
|
|
}
|
2022-01-06 18:36:15 +01:00
|
|
|
|
|
|
|
resetImplicitSize();
|
|
|
|
update();
|
2021-12-23 18:36:32 +01:00
|
|
|
|
2023-03-10 09:18:52 +01:00
|
|
|
if ( isComponentComplete() )
|
|
|
|
Q_EMIT optionsChanged();
|
2022-01-06 18:36:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskMenu::clear()
|
2021-12-23 18:36:32 +01:00
|
|
|
{
|
2023-03-10 12:46:19 +01:00
|
|
|
setOptions( QVector< QskLabelData >() );
|
2021-12-23 18:36:32 +01:00
|
|
|
}
|
|
|
|
|
2023-03-10 09:18:52 +01:00
|
|
|
QVector< QskLabelData > QskMenu::options() const
|
2021-12-23 18:36:32 +01:00
|
|
|
{
|
2023-03-10 09:18:52 +01:00
|
|
|
return m_data->options;
|
|
|
|
}
|
2021-12-27 09:50:14 +01:00
|
|
|
|
2023-03-10 09:18:52 +01:00
|
|
|
QskLabelData QskMenu::optionAt( int index ) const
|
|
|
|
{
|
|
|
|
return m_data->options.value( index );
|
|
|
|
}
|
2021-12-23 18:36:32 +01:00
|
|
|
|
2023-03-10 09:18:52 +01:00
|
|
|
void QskMenu::addSeparator()
|
2023-03-07 14:32:53 +01:00
|
|
|
{
|
2023-05-16 12:49:46 +02:00
|
|
|
addOption( QskLabelData() );
|
2023-03-07 14:32:53 +01:00
|
|
|
}
|
|
|
|
|
2023-05-16 12:49:46 +02:00
|
|
|
QVector< int > QskMenu::separators() const
|
2023-03-07 14:32:53 +01:00
|
|
|
{
|
2023-05-16 12:49:46 +02:00
|
|
|
return m_data->separators;
|
2023-03-07 14:32:53 +01:00
|
|
|
}
|
|
|
|
|
2023-05-16 12:49:46 +02:00
|
|
|
QVector< int > QskMenu::actions() const
|
2021-12-23 18:36:32 +01:00
|
|
|
{
|
2023-05-16 12:49:46 +02:00
|
|
|
return m_data->actions;
|
2021-12-23 18:36:32 +01:00
|
|
|
}
|
|
|
|
|
2023-03-10 12:46:19 +01:00
|
|
|
int QskMenu::currentIndex() const
|
2021-12-23 18:36:32 +01:00
|
|
|
{
|
2023-03-10 12:46:19 +01:00
|
|
|
return m_data->currentIndex;
|
2021-12-23 18:36:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskMenu::setCurrentIndex( int index )
|
|
|
|
{
|
2023-05-16 12:49:46 +02:00
|
|
|
if( index < 0 || index >= m_data->options.count() )
|
|
|
|
{
|
2021-12-29 16:23:19 +01:00
|
|
|
index = -1;
|
2023-05-16 12:49:46 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( m_data->options[index].isEmpty() ) // a seperator
|
|
|
|
index = -1;
|
|
|
|
}
|
2021-12-29 16:23:19 +01:00
|
|
|
|
|
|
|
if( index != m_data->currentIndex )
|
2021-12-23 18:36:32 +01:00
|
|
|
{
|
2021-12-29 16:23:19 +01:00
|
|
|
setPositionHint( Cursor, index );
|
|
|
|
|
2021-12-23 18:36:32 +01:00
|
|
|
m_data->currentIndex = index;
|
|
|
|
update();
|
|
|
|
|
|
|
|
Q_EMIT currentIndexChanged( index );
|
2023-03-06 16:37:28 +01:00
|
|
|
Q_EMIT focusIndicatorRectChanged();
|
2021-12-23 18:36:32 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-10 12:46:19 +01:00
|
|
|
QString QskMenu::currentText() const
|
2021-12-23 18:36:32 +01:00
|
|
|
{
|
2023-03-10 12:46:19 +01:00
|
|
|
return optionAt( m_data->currentIndex ).text();
|
|
|
|
}
|
|
|
|
|
|
|
|
int QskMenu::triggeredIndex() const
|
|
|
|
{
|
|
|
|
return m_data->triggeredIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString QskMenu::triggeredText() const
|
|
|
|
{
|
|
|
|
return optionAt( m_data->triggeredIndex ).text();
|
2021-12-23 18:36:32 +01:00
|
|
|
}
|
|
|
|
|
2023-11-03 18:13:24 +01:00
|
|
|
void QskMenu::updateResources()
|
|
|
|
{
|
|
|
|
qreal dy = 0.0;
|
|
|
|
if ( isFading() )
|
|
|
|
dy = ( 1.0 - fadingFactor() ) * height();
|
|
|
|
|
|
|
|
setPosition( m_data->origin.x(), m_data->origin.y() - dy );
|
|
|
|
|
|
|
|
Inherited::updateResources();
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskMenu::updateNode( QSGNode* node )
|
|
|
|
{
|
|
|
|
if ( isFading() && clip() )
|
|
|
|
{
|
|
|
|
if ( auto clipNode = QQuickItemPrivate::get( this )->clipNode() )
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
The clipRect is changing while fading. Couldn't
|
|
|
|
find a way how to trigger updates - maybe be enabling/disabling
|
|
|
|
the clip. So we do the updates manually. TODO ...
|
|
|
|
*/
|
|
|
|
const auto r = clipRect();
|
|
|
|
if ( r != clipNode->rect() )
|
|
|
|
{
|
|
|
|
clipNode->setRect( r );
|
|
|
|
clipNode->update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Inherited::updateNode( node );
|
|
|
|
}
|
|
|
|
|
2021-12-23 18:36:32 +01:00
|
|
|
void QskMenu::keyPressEvent( QKeyEvent* event )
|
|
|
|
{
|
|
|
|
if( m_data->currentIndex < 0 )
|
|
|
|
return;
|
|
|
|
|
2023-10-25 10:07:38 +02:00
|
|
|
switch( event->key() )
|
2021-12-23 18:36:32 +01:00
|
|
|
{
|
|
|
|
case Qt::Key_Up:
|
|
|
|
{
|
|
|
|
traverse( -1 );
|
2023-10-25 10:07:38 +02:00
|
|
|
return;
|
2021-12-23 18:36:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
case Qt::Key_Down:
|
|
|
|
{
|
|
|
|
traverse( 1 );
|
2023-10-25 10:07:38 +02:00
|
|
|
return;
|
2021-12-23 18:36:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
case Qt::Key_Select:
|
|
|
|
case Qt::Key_Space:
|
2023-03-06 17:37:32 +01:00
|
|
|
case Qt::Key_Return:
|
2023-03-07 13:26:05 +01:00
|
|
|
case Qt::Key_Enter:
|
2021-12-23 18:36:32 +01:00
|
|
|
{
|
|
|
|
m_data->isPressed = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
{
|
2023-03-10 12:46:19 +01:00
|
|
|
if ( const int steps = qskFocusChainIncrement( event ) )
|
2023-10-25 10:07:38 +02:00
|
|
|
{
|
2023-02-14 08:58:37 +01:00
|
|
|
traverse( steps );
|
2023-10-25 10:07:38 +02:00
|
|
|
return;
|
|
|
|
}
|
2021-12-23 18:36:32 +01:00
|
|
|
}
|
|
|
|
}
|
2023-10-25 10:07:38 +02:00
|
|
|
|
|
|
|
return Inherited::keyPressEvent( event );
|
2021-12-23 18:36:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskMenu::keyReleaseEvent( QKeyEvent* )
|
|
|
|
{
|
2023-06-30 15:44:49 +02:00
|
|
|
if( isPressed() )
|
2021-12-23 18:36:32 +01:00
|
|
|
{
|
|
|
|
m_data->isPressed = false;
|
2023-03-10 12:46:19 +01:00
|
|
|
|
|
|
|
if ( m_data->currentIndex >= 0 )
|
|
|
|
{
|
|
|
|
close();
|
2023-05-10 09:14:25 +02:00
|
|
|
trigger( m_data->currentIndex );
|
2023-03-10 12:46:19 +01:00
|
|
|
}
|
2021-12-23 18:36:32 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-30 15:28:20 +02:00
|
|
|
void QskMenu::hoverEnterEvent( QHoverEvent* event )
|
|
|
|
{
|
|
|
|
using A = QskAspect;
|
|
|
|
|
|
|
|
setSkinHint( Segment | Hovered | A::Metric | A::Position, qskHoverPosition( event ) );
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskMenu::hoverMoveEvent( QHoverEvent* event )
|
|
|
|
{
|
|
|
|
using A = QskAspect;
|
|
|
|
|
|
|
|
setSkinHint( Segment | Hovered | A::Metric | A::Position, qskHoverPosition( event ) );
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskMenu::hoverLeaveEvent( QHoverEvent* )
|
|
|
|
{
|
|
|
|
using A = QskAspect;
|
|
|
|
|
|
|
|
setSkinHint( Segment | Hovered | A::Metric | A::Position, QPointF() );
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
2022-01-05 11:59:32 +01:00
|
|
|
#ifndef QT_NO_WHEELEVENT
|
|
|
|
|
2021-12-23 18:36:32 +01:00
|
|
|
void QskMenu::wheelEvent( QWheelEvent* event )
|
|
|
|
{
|
2022-01-05 11:59:32 +01:00
|
|
|
const auto steps = qskWheelSteps( event );
|
|
|
|
traverse( -steps );
|
2021-12-23 18:36:32 +01:00
|
|
|
}
|
|
|
|
|
2022-01-05 11:59:32 +01:00
|
|
|
#endif
|
|
|
|
|
2021-12-23 18:36:32 +01:00
|
|
|
void QskMenu::traverse( int steps )
|
|
|
|
{
|
2023-05-16 12:49:46 +02:00
|
|
|
const auto& actions = m_data->actions;
|
|
|
|
const auto count = actions.count();
|
|
|
|
|
|
|
|
// -1 -> only one entry ?
|
|
|
|
if ( actions.isEmpty() || ( steps % count == 0 ) )
|
2021-12-29 16:23:19 +01:00
|
|
|
return;
|
2021-12-23 18:36:32 +01:00
|
|
|
|
2023-05-16 12:49:46 +02:00
|
|
|
int action1 = qskActionIndex( actions, m_data->currentIndex );
|
|
|
|
int action2 = action1 + steps;
|
2021-12-23 18:36:32 +01:00
|
|
|
|
2023-05-16 12:49:46 +02:00
|
|
|
// when cycling we want to slide in
|
|
|
|
int index1;
|
2021-12-29 16:23:19 +01:00
|
|
|
|
2023-05-16 12:49:46 +02:00
|
|
|
if ( action2 < 0 )
|
|
|
|
index1 = m_data->options.count();
|
|
|
|
else if ( action2 >= count )
|
|
|
|
index1 = -1;
|
|
|
|
else
|
|
|
|
index1 = actions[ action1 ];
|
2021-12-29 16:23:19 +01:00
|
|
|
|
2023-05-16 12:49:46 +02:00
|
|
|
action2 %= count;
|
|
|
|
if ( action2 < 0 )
|
|
|
|
action2 += count;
|
2021-12-29 16:23:19 +01:00
|
|
|
|
2023-05-16 12:49:46 +02:00
|
|
|
const auto index2 = actions[ action2 ];
|
2021-12-29 16:23:19 +01:00
|
|
|
|
2023-05-16 12:49:46 +02:00
|
|
|
movePositionHint( Cursor, index1, index2 );
|
|
|
|
setCurrentIndex( index2 );
|
2021-12-23 18:36:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskMenu::mousePressEvent( QMouseEvent* event )
|
|
|
|
{
|
2021-12-29 15:21:09 +01:00
|
|
|
// QGuiApplication::styleHints()->setFocusOnTouchRelease ??
|
|
|
|
|
2021-12-23 18:36:32 +01:00
|
|
|
if ( event->button() == Qt::LeftButton )
|
|
|
|
{
|
2021-12-29 15:21:09 +01:00
|
|
|
const auto index = indexAtPosition( qskMousePosition( event ) );
|
2021-12-24 16:20:34 +01:00
|
|
|
if ( index >= 0 )
|
|
|
|
{
|
|
|
|
setCurrentIndex( index );
|
2021-12-23 18:36:32 +01:00
|
|
|
m_data->isPressed = true;
|
2021-12-24 16:20:34 +01:00
|
|
|
}
|
2022-01-04 15:54:16 +01:00
|
|
|
|
|
|
|
return;
|
2021-12-23 18:36:32 +01:00
|
|
|
}
|
2022-01-04 15:54:16 +01:00
|
|
|
|
2022-03-24 17:10:11 +01:00
|
|
|
Inherited::mousePressEvent( event );
|
2021-12-23 18:36:32 +01:00
|
|
|
}
|
|
|
|
|
2023-03-10 09:18:52 +01:00
|
|
|
void QskMenu::mouseUngrabEvent()
|
|
|
|
{
|
|
|
|
m_data->isPressed = false;
|
|
|
|
Inherited::mouseUngrabEvent();
|
|
|
|
}
|
|
|
|
|
2021-12-23 18:36:32 +01:00
|
|
|
void QskMenu::mouseReleaseEvent( QMouseEvent* event )
|
|
|
|
{
|
|
|
|
if ( event->button() == Qt::LeftButton )
|
|
|
|
{
|
2023-06-30 15:44:49 +02:00
|
|
|
if( isPressed() )
|
2021-12-23 18:36:32 +01:00
|
|
|
{
|
|
|
|
m_data->isPressed = false;
|
2021-12-24 16:20:34 +01:00
|
|
|
|
2023-03-10 12:46:19 +01:00
|
|
|
const auto index = m_data->currentIndex;
|
|
|
|
|
|
|
|
if ( ( index >= 0 )
|
|
|
|
&& ( index == indexAtPosition( qskMousePosition( event ) ) ) )
|
|
|
|
{
|
|
|
|
close();
|
2023-05-10 09:14:25 +02:00
|
|
|
trigger( m_data->currentIndex );
|
2023-03-10 12:46:19 +01:00
|
|
|
}
|
2021-12-23 18:36:32 +01:00
|
|
|
}
|
2022-01-04 15:54:16 +01:00
|
|
|
|
|
|
|
return;
|
2021-12-23 18:36:32 +01:00
|
|
|
}
|
2022-01-04 15:54:16 +01:00
|
|
|
|
2022-03-24 17:10:11 +01:00
|
|
|
Inherited::mouseReleaseEvent( event );
|
2021-12-23 18:36:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void QskMenu::aboutToShow()
|
2021-12-23 19:05:59 +01:00
|
|
|
{
|
2023-11-03 18:13:24 +01:00
|
|
|
setSize( sizeConstraint() );
|
2021-12-29 16:23:19 +01:00
|
|
|
|
|
|
|
if ( m_data->currentIndex < 0 )
|
2023-05-16 12:49:46 +02:00
|
|
|
{
|
|
|
|
if ( !m_data->actions.isEmpty() )
|
|
|
|
setCurrentIndex( m_data->actions.first() );
|
|
|
|
}
|
2021-12-29 16:23:19 +01:00
|
|
|
|
2021-12-23 18:36:32 +01:00
|
|
|
Inherited::aboutToShow();
|
|
|
|
}
|
|
|
|
|
|
|
|
QRectF QskMenu::focusIndicatorRect() const
|
|
|
|
{
|
2023-11-03 18:13:24 +01:00
|
|
|
if ( isFading() )
|
2023-03-06 16:37:28 +01:00
|
|
|
return QRectF();
|
|
|
|
|
2023-02-14 08:58:37 +01:00
|
|
|
if( currentIndex() >= 0 )
|
|
|
|
{
|
2023-05-16 12:49:46 +02:00
|
|
|
auto actionIndex = qskActionIndex( m_data->actions, currentIndex() );
|
|
|
|
|
2023-02-14 08:58:37 +01:00
|
|
|
return effectiveSkinlet()->sampleRect( this,
|
2023-05-16 12:49:46 +02:00
|
|
|
contentsRect(), Segment, actionIndex );
|
2023-02-14 08:58:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return Inherited::focusIndicatorRect();
|
2021-12-23 18:36:32 +01:00
|
|
|
}
|
|
|
|
|
2021-12-24 16:20:34 +01:00
|
|
|
QRectF QskMenu::cellRect( int index ) const
|
|
|
|
{
|
2023-05-16 12:49:46 +02:00
|
|
|
const auto actionIndex = qskActionIndex( m_data->actions, index );
|
|
|
|
|
2021-12-28 16:14:30 +01:00
|
|
|
return effectiveSkinlet()->sampleRect(
|
2023-05-16 12:49:46 +02:00
|
|
|
this, contentsRect(), QskMenu::Segment, actionIndex );
|
2021-12-24 16:20:34 +01:00
|
|
|
}
|
|
|
|
|
2021-12-26 09:15:15 +01:00
|
|
|
int QskMenu::indexAtPosition( const QPointF& pos ) const
|
|
|
|
{
|
2023-05-16 12:49:46 +02:00
|
|
|
const auto index = effectiveSkinlet()->sampleIndexAt(
|
2022-04-20 13:58:53 +02:00
|
|
|
this, contentsRect(), QskMenu::Segment, pos );
|
2023-05-16 12:49:46 +02:00
|
|
|
|
|
|
|
return m_data->actions.value( index, -1 );
|
2021-12-26 09:15:15 +01:00
|
|
|
}
|
|
|
|
|
2023-06-30 15:44:49 +02:00
|
|
|
bool QskMenu::isPressed() const
|
|
|
|
{
|
|
|
|
return m_data->isPressed;
|
|
|
|
}
|
|
|
|
|
2023-03-10 12:46:19 +01:00
|
|
|
void QskMenu::trigger( int index )
|
|
|
|
{
|
2023-05-16 12:49:46 +02:00
|
|
|
if ( index >= 0 && index < m_data->options.count() )
|
2023-03-10 12:46:19 +01:00
|
|
|
{
|
|
|
|
m_data->triggeredIndex = index;
|
|
|
|
Q_EMIT triggered( index );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-03 18:13:24 +01:00
|
|
|
QskAspect QskMenu::fadingAspect() const
|
|
|
|
{
|
|
|
|
return QskMenu::Panel | QskAspect::Position;
|
|
|
|
}
|
|
|
|
|
2021-12-30 11:13:48 +01:00
|
|
|
int QskMenu::exec()
|
|
|
|
{
|
2022-01-01 18:13:33 +01:00
|
|
|
(void) execPopup();
|
2023-03-10 12:46:19 +01:00
|
|
|
return m_data->triggeredIndex;
|
2021-12-30 11:13:48 +01:00
|
|
|
}
|
|
|
|
|
2021-12-23 18:36:32 +01:00
|
|
|
#include "moc_QskMenu.cpp"
|