QskFocusIndicator::duration introduced
This commit is contained in:
parent
6fa8cd9dc3
commit
2419183397
@ -12,7 +12,6 @@ set(SOURCES
|
||||
dialog/DialogPage.h dialog/DialogPage.cpp
|
||||
listbox/ListBoxPage.h listbox/ListBoxPage.cpp
|
||||
Page.h Page.cpp
|
||||
FocusIndicator.h FocusIndicator.cpp
|
||||
main.cpp
|
||||
)
|
||||
qt_add_resources(SOURCES icons.qrc)
|
||||
|
@ -1,218 +0,0 @@
|
||||
#include "FocusIndicator.h"
|
||||
|
||||
#include <QskEvent.h>
|
||||
#include <QskAnimationHint.h>
|
||||
|
||||
#include <qquickwindow.h>
|
||||
#include <qbasictimer.h>
|
||||
|
||||
static inline bool qskIsEnablingKey( const QKeyEvent* event )
|
||||
{
|
||||
// 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; }
|
||||
|
||||
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 )
|
||||
{
|
||||
ms = std::max( ms, 0 );
|
||||
if ( ms == m_data->duration )
|
||||
return;
|
||||
|
||||
m_data->duration = ms;
|
||||
|
||||
if ( m_data->isAutoDisabling() )
|
||||
{
|
||||
if ( auto w = window() )
|
||||
w->installEventFilter( this );
|
||||
|
||||
if ( isEnabled() )
|
||||
{
|
||||
if ( isInitiallyPainted() )
|
||||
m_data->timer.start( m_data->duration, this );
|
||||
else
|
||||
setEnabled( false );
|
||||
}
|
||||
|
||||
connect( this, &QQuickItem::enabledChanged,
|
||||
this, &FocusIndicator::resetTimer );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( auto w = window() )
|
||||
w->removeEventFilter( this );
|
||||
|
||||
setEnabled( true );
|
||||
|
||||
disconnect( this, &QQuickItem::enabledChanged,
|
||||
this, &FocusIndicator::resetTimer );
|
||||
}
|
||||
|
||||
Q_EMIT durationChanged( ms );
|
||||
}
|
||||
|
||||
int FocusIndicator::duration() const
|
||||
{
|
||||
return m_data->duration;
|
||||
}
|
||||
|
||||
void FocusIndicator::maybeEnable( bool on )
|
||||
{
|
||||
if ( !m_data->isAutoEnabling() )
|
||||
return;
|
||||
|
||||
if ( on )
|
||||
{
|
||||
if ( auto w = window() )
|
||||
{
|
||||
if ( w->isExposed() && w->isActive() )
|
||||
setEnabled( true );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setEnabled( false );
|
||||
}
|
||||
}
|
||||
|
||||
void FocusIndicator::resetTimer()
|
||||
{
|
||||
if ( m_data->isAutoDisabling() )
|
||||
{
|
||||
if ( isEnabled() )
|
||||
{
|
||||
const auto hint = animationHint( Panel | QskAspect::Color );
|
||||
m_data->timer.start( m_data->duration + hint.duration, this );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_data->timer.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FocusIndicator::eventFilter( QObject* object, QEvent* event )
|
||||
{
|
||||
if( ( object != window() ) || !m_data->isAutoDisabling() )
|
||||
return Inherited::eventFilter( object, event );
|
||||
|
||||
switch( static_cast< int >( event->type() ) )
|
||||
{
|
||||
case QEvent::KeyPress:
|
||||
case QEvent::KeyRelease:
|
||||
case QEvent::ShortcutOverride:
|
||||
{
|
||||
if ( m_data->timer.isActive() )
|
||||
{
|
||||
// renew the exposed period
|
||||
m_data->timer.start( m_data->duration, this );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch( static_cast< int >( event->type() ) )
|
||||
{
|
||||
case QEvent::KeyPress:
|
||||
{
|
||||
const auto keyEvent = static_cast< QKeyEvent* >( event );
|
||||
|
||||
if( keyEvent->isAutoRepeat() && m_data->blockAutoRepeatKeyEvents )
|
||||
{
|
||||
/*
|
||||
We swallow all auto repeated events to avoid running along
|
||||
the tab chain by accident.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( !isEnabled() && qskIsEnablingKey( keyEvent ) )
|
||||
{
|
||||
setEnabled( true );
|
||||
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;
|
||||
}
|
||||
|
||||
case QEvent::Expose:
|
||||
case QEvent::FocusIn:
|
||||
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() )
|
||||
{
|
||||
if ( auto w = event->oldWindow() )
|
||||
w->removeEventFilter( this );
|
||||
|
||||
if( auto w = event->window() )
|
||||
{
|
||||
w->installEventFilter( this );
|
||||
maybeEnable( true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FocusIndicator::timerEvent( QTimerEvent* event )
|
||||
{
|
||||
if ( m_data->isAutoDisabling() )
|
||||
{
|
||||
if( event->timerId() == m_data->timer.timerId() )
|
||||
{
|
||||
setEnabled( false );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Inherited::timerEvent( event );
|
||||
}
|
||||
|
||||
#include "moc_FocusIndicator.cpp"
|
@ -1,36 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QskFocusIndicator.h>
|
||||
|
||||
class FocusIndicator : public QskFocusIndicator
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY( int duration READ duration
|
||||
WRITE setDuration NOTIFY durationChanged )
|
||||
|
||||
using Inherited = QskFocusIndicator;
|
||||
|
||||
public:
|
||||
FocusIndicator( QQuickItem* parent = nullptr );
|
||||
~FocusIndicator() override;
|
||||
|
||||
bool eventFilter( QObject*, QEvent* ) override;
|
||||
|
||||
void setDuration( int ms );
|
||||
int duration() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void durationChanged( int );
|
||||
|
||||
protected:
|
||||
void windowChangeEvent( QskWindowChangeEvent* ) override;
|
||||
void timerEvent( QTimerEvent* ) override;
|
||||
|
||||
private:
|
||||
void resetTimer();
|
||||
void maybeEnable( bool );
|
||||
|
||||
class PrivateData;
|
||||
std::unique_ptr< PrivateData > m_data;
|
||||
};
|
@ -3,7 +3,6 @@
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#include "FocusIndicator.h"
|
||||
#include "label/LabelPage.h"
|
||||
#include "progressbar/ProgressBarPage.h"
|
||||
#include "inputs/InputPage.h"
|
||||
@ -297,7 +296,7 @@ int main( int argc, char* argv[] )
|
||||
|
||||
QskWindow window;
|
||||
window.addItem( mainView );
|
||||
window.addItem( new FocusIndicator() );
|
||||
window.addItem( new QskFocusIndicator() );
|
||||
|
||||
window.resize( 800, 600 );
|
||||
window.show();
|
||||
|
@ -5,11 +5,13 @@
|
||||
|
||||
#include "QskFocusIndicator.h"
|
||||
#include "QskAspect.h"
|
||||
#include "QskAnimationHint.h"
|
||||
#include "QskEvent.h"
|
||||
#include "QskQuick.h"
|
||||
|
||||
#include <qpointer.h>
|
||||
#include <qquickwindow.h>
|
||||
#include <qbasictimer.h>
|
||||
|
||||
QSK_QT_PRIVATE_BEGIN
|
||||
#include <private/qquickitem_p.h>
|
||||
@ -52,6 +54,12 @@ static inline QskAspect::Section qskItemSection( const QQuickItem* item )
|
||||
return QskAspect::Body;
|
||||
}
|
||||
|
||||
static inline bool qskIsEnablingKey( const QKeyEvent* event )
|
||||
{
|
||||
// what keys do we want have here ???
|
||||
return qskIsButtonPressKey( event ) || qskFocusChainIncrement( event );
|
||||
}
|
||||
|
||||
class QskFocusIndicator::PrivateData
|
||||
{
|
||||
public:
|
||||
@ -63,8 +71,16 @@ class QskFocusIndicator::PrivateData
|
||||
connections.clear();
|
||||
}
|
||||
|
||||
inline bool isAutoDisabling() const { return duration > 0; }
|
||||
inline bool isAutoEnabling() const { return false; }
|
||||
|
||||
QPointer< QQuickItem > clippingItem;
|
||||
QVector< QMetaObject::Connection > connections;
|
||||
|
||||
int duration = 0;
|
||||
QBasicTimer timer;
|
||||
|
||||
bool blockAutoRepeatKeyEvents = false;
|
||||
};
|
||||
|
||||
QskFocusIndicator::QskFocusIndicator( QQuickItem* parent )
|
||||
@ -73,12 +89,177 @@ QskFocusIndicator::QskFocusIndicator( QQuickItem* parent )
|
||||
{
|
||||
setPlacementPolicy( QskPlacementPolicy::Ignore );
|
||||
connectWindow( window(), true );
|
||||
|
||||
setDuration( 4500 );
|
||||
}
|
||||
|
||||
QskFocusIndicator::~QskFocusIndicator()
|
||||
{
|
||||
}
|
||||
|
||||
void QskFocusIndicator::setDuration( int ms )
|
||||
{
|
||||
ms = std::max( ms, 0 );
|
||||
if ( ms == m_data->duration )
|
||||
return;
|
||||
|
||||
m_data->duration = ms;
|
||||
|
||||
if ( m_data->isAutoDisabling() )
|
||||
{
|
||||
if ( auto w = window() )
|
||||
w->installEventFilter( this );
|
||||
|
||||
if ( isEnabled() )
|
||||
{
|
||||
if ( isInitiallyPainted() )
|
||||
m_data->timer.start( m_data->duration, this );
|
||||
else
|
||||
setEnabled( false );
|
||||
}
|
||||
|
||||
connect( this, &QQuickItem::enabledChanged,
|
||||
this, &QskFocusIndicator::resetTimer );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( auto w = window() )
|
||||
w->removeEventFilter( this );
|
||||
|
||||
setEnabled( true );
|
||||
|
||||
disconnect( this, &QQuickItem::enabledChanged,
|
||||
this, &QskFocusIndicator::resetTimer );
|
||||
}
|
||||
|
||||
Q_EMIT durationChanged( ms );
|
||||
}
|
||||
|
||||
int QskFocusIndicator::duration() const
|
||||
{
|
||||
return m_data->duration;
|
||||
}
|
||||
|
||||
void QskFocusIndicator::maybeEnable( bool on )
|
||||
{
|
||||
if ( !m_data->isAutoEnabling() )
|
||||
return;
|
||||
|
||||
if ( on )
|
||||
{
|
||||
if ( auto w = window() )
|
||||
{
|
||||
if ( w->isExposed() && w->isActive() )
|
||||
setEnabled( true );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setEnabled( false );
|
||||
}
|
||||
}
|
||||
|
||||
void QskFocusIndicator::resetTimer()
|
||||
{
|
||||
if ( m_data->isAutoDisabling() )
|
||||
{
|
||||
if ( isEnabled() )
|
||||
{
|
||||
const auto hint = animationHint( Panel | QskAspect::Color );
|
||||
m_data->timer.start( m_data->duration + hint.duration, this );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_data->timer.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool QskFocusIndicator::eventFilter( QObject* object, QEvent* event )
|
||||
{
|
||||
if( ( object != window() ) || !m_data->isAutoDisabling() )
|
||||
return Inherited::eventFilter( object, event );
|
||||
|
||||
switch( static_cast< int >( event->type() ) )
|
||||
{
|
||||
case QEvent::KeyPress:
|
||||
case QEvent::KeyRelease:
|
||||
case QEvent::ShortcutOverride:
|
||||
{
|
||||
if ( m_data->timer.isActive() )
|
||||
{
|
||||
// renew the exposed period
|
||||
m_data->timer.start( m_data->duration, this );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch( static_cast< int >( event->type() ) )
|
||||
{
|
||||
case QEvent::KeyPress:
|
||||
{
|
||||
const auto keyEvent = static_cast< QKeyEvent* >( event );
|
||||
|
||||
if( keyEvent->isAutoRepeat() && m_data->blockAutoRepeatKeyEvents )
|
||||
{
|
||||
/*
|
||||
We swallow all auto repeated events to avoid running along
|
||||
the tab chain by accident.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( !isEnabled() && qskIsEnablingKey( keyEvent ) )
|
||||
{
|
||||
setEnabled( true );
|
||||
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;
|
||||
}
|
||||
|
||||
case QEvent::Expose:
|
||||
case QEvent::FocusIn:
|
||||
case QEvent::FocusOut:
|
||||
{
|
||||
maybeEnable( event->type() != QEvent::FocusOut );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Inherited::eventFilter( object, event );
|
||||
}
|
||||
|
||||
void QskFocusIndicator::timerEvent( QTimerEvent* event )
|
||||
{
|
||||
if ( m_data->isAutoDisabling() )
|
||||
{
|
||||
if( event->timerId() == m_data->timer.timerId() )
|
||||
{
|
||||
setEnabled( false );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Inherited::timerEvent( event );
|
||||
}
|
||||
|
||||
bool QskFocusIndicator::contains( const QPointF& ) const
|
||||
{
|
||||
// so that tools like Squish do not see it
|
||||
@ -213,6 +394,18 @@ void QskFocusIndicator::windowChangeEvent( QskWindowChangeEvent* event )
|
||||
connectWindow( event->window(), true );
|
||||
|
||||
onFocusItemChanged();
|
||||
|
||||
if ( m_data->isAutoDisabling() )
|
||||
{
|
||||
if ( auto w = event->oldWindow() )
|
||||
w->removeEventFilter( this );
|
||||
|
||||
if( auto w = event->window() )
|
||||
{
|
||||
w->installEventFilter( this );
|
||||
maybeEnable( true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QskFocusIndicator::connectWindow( const QQuickWindow* window, bool on )
|
||||
|
@ -14,17 +14,34 @@ class QSK_EXPORT QskFocusIndicator : public QskControl
|
||||
|
||||
using Inherited = QskControl;
|
||||
|
||||
Q_PROPERTY( int duration READ duration
|
||||
WRITE setDuration NOTIFY durationChanged )
|
||||
|
||||
public:
|
||||
QSK_SUBCONTROLS( Panel )
|
||||
|
||||
QskFocusIndicator( QQuickItem* parent = nullptr );
|
||||
~QskFocusIndicator() override;
|
||||
|
||||
/*
|
||||
duration until the indicator goes into disabled state after being enabled.
|
||||
A duration of 0 disables automatic state changes.
|
||||
*/
|
||||
void setDuration( int ms );
|
||||
int duration() const;
|
||||
|
||||
bool contains( const QPointF& ) const override;
|
||||
QRectF clipRect() const override;
|
||||
|
||||
bool eventFilter( QObject*, QEvent* ) override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void durationChanged( int );
|
||||
|
||||
protected:
|
||||
void windowChangeEvent( QskWindowChangeEvent* ) override;
|
||||
void timerEvent( QTimerEvent* ) override;
|
||||
|
||||
virtual QRectF focusRect() const;
|
||||
void updateFocusFrame();
|
||||
|
||||
@ -35,6 +52,9 @@ class QSK_EXPORT QskFocusIndicator : public QskControl
|
||||
void onFocusItemChanged();
|
||||
void onFocusItemDestroyed();
|
||||
|
||||
void resetTimer();
|
||||
void maybeEnable( bool );
|
||||
|
||||
void connectWindow( const QQuickWindow*, bool on );
|
||||
QVector< QMetaObject::Connection > connectItem( const QQuickItem* );
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user