qskinny/examples/gallery/FocusIndicator.cpp

219 lines
4.9 KiB
C++
Raw Normal View History

#include "FocusIndicator.h"
#include <QskEvent.h>
#include <QskAnimationHint.h>
2023-12-01 18:43:31 +01:00
#include <qquickwindow.h>
#include <qbasictimer.h>
static inline bool qskIsEnablingKey( const QKeyEvent* event )
{
2023-12-01 18:43:31 +01:00
// what keys do we want have here ???
return qskIsButtonPressKey( event ) || qskFocusChainIncrement( event );
}
class FocusIndicator::PrivateData
{
public:
inline bool isAutoDisabling() const { return duration > 0; }
inline bool isAutoEnabling() const { return false; }
2023-12-01 18:43:31 +01:00
int duration = 0;
QBasicTimer timer;
bool blockAutoRepeatKeyEvents = false;
};
FocusIndicator::FocusIndicator( QQuickItem* parent )
: Inherited( parent )
, m_data( new PrivateData() )
{
setDuration( 4500 );
}
FocusIndicator::~FocusIndicator()
{
}
void FocusIndicator::setDuration( int ms )
{
2023-12-01 18:43:31 +01:00
ms = std::max( ms, 0 );
if ( ms == m_data->duration )
return;
m_data->duration = ms;
if ( m_data->isAutoDisabling() )
2023-12-01 18:43:31 +01:00
{
if ( auto w = window() )
w->installEventFilter( this );
if ( isEnabled() )
2023-12-01 18:43:31 +01:00
{
if ( isInitiallyPainted() )
m_data->timer.start( m_data->duration, this );
2023-12-01 18:43:31 +01:00
else
setEnabled( false );
2023-12-01 18:43:31 +01:00
}
connect( this, &QQuickItem::enabledChanged,
this, &FocusIndicator::resetTimer );
2023-12-01 18:43:31 +01:00
}
else
{
if ( auto w = window() )
w->removeEventFilter( this );
setEnabled( true );
disconnect( this, &QQuickItem::enabledChanged,
this, &FocusIndicator::resetTimer );
2023-12-01 18:43:31 +01:00
}
Q_EMIT durationChanged( ms );
2023-12-01 18:43:31 +01:00
}
int FocusIndicator::duration() const
2023-12-01 18:43:31 +01:00
{
return m_data->duration;
2023-12-01 18:43:31 +01:00
}
void FocusIndicator::maybeEnable( bool on )
2023-12-01 18:43:31 +01:00
{
if ( !m_data->isAutoEnabling() )
2023-12-01 18:43:31 +01:00
return;
if ( on )
{
if ( auto w = window() )
{
if ( w->isExposed() && w->isActive() )
setEnabled( true );
}
}
else
{
setEnabled( false );
}
}
2023-12-01 18:43:31 +01:00
void FocusIndicator::resetTimer()
{
if ( m_data->isAutoDisabling() )
2023-12-01 18:43:31 +01:00
{
if ( isEnabled() )
2023-12-01 18:43:31 +01:00
{
const auto hint = animationHint( Panel | QskAspect::Color );
m_data->timer.start( m_data->duration + hint.duration, this );
2023-12-01 18:43:31 +01:00
}
else
{
m_data->timer.stop();
2023-12-01 18:43:31 +01:00
}
}
}
bool FocusIndicator::eventFilter( QObject* object, QEvent* event )
{
if( ( object != window() ) || !m_data->isAutoDisabling() )
return Inherited::eventFilter( object, event );
2023-12-01 18:43:31 +01:00
switch( static_cast< int >( event->type() ) )
{
case QEvent::KeyPress:
case QEvent::KeyRelease:
case QEvent::ShortcutOverride:
{
if ( m_data->timer.isActive() )
2023-12-01 18:43:31 +01:00
{
// renew the exposed period
m_data->timer.start( m_data->duration, this );
2023-12-01 18:43:31 +01:00
}
break;
}
2023-12-01 18:43:31 +01:00
}
switch( static_cast< int >( event->type() ) )
{
case QEvent::KeyPress:
{
const auto keyEvent = static_cast< QKeyEvent* >( event );
if( keyEvent->isAutoRepeat() && m_data->blockAutoRepeatKeyEvents )
{
2023-12-01 18:43:31 +01:00
/*
We swallow all auto repeated events to avoid running along
the tab chain by accident.
*/
return true;
}
if ( !isEnabled() && qskIsEnablingKey( keyEvent ) )
{
setEnabled( true );
2023-12-01 18:43:31 +01:00
m_data->blockAutoRepeatKeyEvents = true;
return true;
}
m_data->blockAutoRepeatKeyEvents = false;
break;
}
case QEvent::KeyRelease:
{
if( m_data->blockAutoRepeatKeyEvents )
{
if( !static_cast< QKeyEvent* >( event )->isAutoRepeat() )
m_data->blockAutoRepeatKeyEvents = false;
return true;
}
break;
}
2023-12-01 18:43:31 +01:00
case QEvent::Expose:
case QEvent::FocusIn:
2023-12-01 18:43:31 +01:00
case QEvent::FocusOut:
{
maybeEnable( event->type() != QEvent::FocusOut );
break;
}
}
return Inherited::eventFilter( object, event );
}
void FocusIndicator::windowChangeEvent( QskWindowChangeEvent* event )
{
Inherited::windowChangeEvent( event );
if ( m_data->isAutoDisabling() )
2023-12-01 18:43:31 +01:00
{
if ( auto w = event->oldWindow() )
w->removeEventFilter( this );
2023-12-01 18:43:31 +01:00
if( auto w = event->window() )
{
w->installEventFilter( this );
maybeEnable( true );
2023-12-01 18:43:31 +01:00
}
}
}
void FocusIndicator::timerEvent( QTimerEvent* event )
{
if ( m_data->isAutoDisabling() )
{
if( event->timerId() == m_data->timer.timerId() )
{
setEnabled( false );
2023-12-01 18:43:31 +01:00
return;
}
}
Inherited::timerEvent( event );
}
#include "moc_FocusIndicator.cpp"