2017-07-21 18:21:34 +02:00
|
|
|
/******************************************************************************
|
|
|
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
|
|
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
|
|
|
*****************************************************************************/
|
|
|
|
|
2019-05-12 13:54:22 +02:00
|
|
|
#include "QskShortcutQml.h"
|
|
|
|
#include <QskShortcutMap.h>
|
2018-07-19 14:10:48 +02:00
|
|
|
|
|
|
|
#include <qquickitem.h>
|
|
|
|
#include <qquickwindow.h>
|
|
|
|
|
|
|
|
QSK_QT_PRIVATE_BEGIN
|
2017-12-03 17:58:18 +01:00
|
|
|
#include <QtGui/private/qguiapplication_p.h>
|
2018-07-19 14:10:48 +02:00
|
|
|
QSK_QT_PRIVATE_END
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-12-05 17:40:21 +01:00
|
|
|
static inline QShortcutMap& qskShortcutMap()
|
|
|
|
{
|
|
|
|
return QGuiApplicationPrivate::instance()->shortcutMap;
|
|
|
|
}
|
|
|
|
|
2017-12-06 17:01:10 +01:00
|
|
|
static bool qskContextMatcher( QObject* object, Qt::ShortcutContext context )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2017-12-06 17:01:10 +01:00
|
|
|
if ( context == Qt::ApplicationShortcut )
|
|
|
|
return true;
|
2017-12-05 13:10:50 +01:00
|
|
|
|
2017-12-06 17:01:10 +01:00
|
|
|
if ( context == Qt::WindowShortcut )
|
|
|
|
{
|
2019-05-12 13:54:22 +02:00
|
|
|
if ( const auto shortcut = qobject_cast< const QskShortcutQml* >( object ) )
|
2017-12-06 17:01:10 +01:00
|
|
|
return shortcut->isFocusInScope();
|
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-12-06 17:01:10 +01:00
|
|
|
return false;
|
|
|
|
}
|
2017-12-05 17:40:21 +01:00
|
|
|
|
2019-05-12 13:54:22 +02:00
|
|
|
class QskShortcutQml::PrivateData
|
2017-12-06 17:01:10 +01:00
|
|
|
{
|
2018-08-03 08:15:28 +02:00
|
|
|
public:
|
|
|
|
PrivateData()
|
|
|
|
: id( 0 )
|
|
|
|
, autoRepeat( true )
|
|
|
|
, enabled( true )
|
|
|
|
, isWindowContext( true )
|
|
|
|
, isComplete( true )
|
2017-12-06 17:01:10 +01:00
|
|
|
{
|
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-12-06 17:01:10 +01:00
|
|
|
~PrivateData()
|
|
|
|
{
|
|
|
|
if ( id != 0 )
|
|
|
|
qskShortcutMap().removeShortcut( id, nullptr );
|
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2019-05-12 13:54:22 +02:00
|
|
|
void resetShortcut( QskShortcutQml* shortcut )
|
2017-12-06 17:01:10 +01:00
|
|
|
{
|
|
|
|
if ( !isComplete )
|
|
|
|
return;
|
2017-12-05 13:10:50 +01:00
|
|
|
|
2017-12-06 17:01:10 +01:00
|
|
|
auto& map = qskShortcutMap();
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-12-06 17:01:10 +01:00
|
|
|
const int oldId = id;
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-12-06 17:01:10 +01:00
|
|
|
if ( id != 0 )
|
2017-12-05 13:10:50 +01:00
|
|
|
{
|
2017-12-06 17:01:10 +01:00
|
|
|
map.removeShortcut( id, nullptr );
|
|
|
|
id = 0;
|
2017-12-05 13:10:50 +01:00
|
|
|
}
|
|
|
|
|
2017-12-06 17:01:10 +01:00
|
|
|
if ( !sequence.isEmpty() )
|
2017-12-03 17:58:18 +01:00
|
|
|
{
|
2017-12-06 17:01:10 +01:00
|
|
|
id = map.addShortcut( shortcut, sequence,
|
|
|
|
shortcut->context(), qskContextMatcher );
|
|
|
|
|
|
|
|
if ( !autoRepeat )
|
|
|
|
map.setShortcutAutoRepeat( false, id, shortcut );
|
|
|
|
|
|
|
|
if ( !enabled )
|
|
|
|
map.setShortcutEnabled( false, id, shortcut );
|
2017-12-03 17:58:18 +01:00
|
|
|
}
|
|
|
|
|
2017-12-06 17:01:10 +01:00
|
|
|
if ( oldId != id )
|
2018-08-03 11:11:42 +02:00
|
|
|
Q_EMIT shortcut->shortcutIdChanged( id );
|
2017-12-06 17:01:10 +01:00
|
|
|
}
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
public:
|
2017-12-06 17:01:10 +01:00
|
|
|
QKeySequence sequence;
|
|
|
|
|
|
|
|
int id;
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-12-06 17:01:10 +01:00
|
|
|
bool autoRepeat : 1;
|
|
|
|
bool enabled : 1;
|
|
|
|
bool isWindowContext : 1;
|
|
|
|
bool isComplete : 1;
|
2017-07-21 18:21:34 +02:00
|
|
|
};
|
|
|
|
|
2019-05-12 13:54:22 +02:00
|
|
|
QskShortcutQml::QskShortcutQml( QObject* parent )
|
2018-08-03 08:15:28 +02:00
|
|
|
: Inherited( parent )
|
|
|
|
, m_data( new PrivateData )
|
2017-12-05 13:10:50 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-05-12 13:54:22 +02:00
|
|
|
QskShortcutQml::QskShortcutQml( const QKeySequence& sequence, QObject* parent )
|
|
|
|
: QskShortcutQml( sequence, Qt::WindowShortcut, parent )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2017-12-06 17:01:10 +01:00
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2019-05-12 13:54:22 +02:00
|
|
|
QskShortcutQml::QskShortcutQml( const QKeySequence& sequence,
|
2018-08-03 08:15:28 +02:00
|
|
|
Qt::ShortcutContext context, QObject* parent )
|
|
|
|
: Inherited( parent )
|
|
|
|
, m_data( new PrivateData )
|
2017-12-06 17:01:10 +01:00
|
|
|
{
|
|
|
|
m_data->sequence = sequence;
|
|
|
|
m_data->isWindowContext = ( context == Qt::WindowShortcut );
|
|
|
|
m_data->resetShortcut( this );
|
|
|
|
}
|
2017-12-05 13:10:50 +01:00
|
|
|
|
2019-05-12 13:54:22 +02:00
|
|
|
QskShortcutQml::~QskShortcutQml()
|
2017-12-06 17:01:10 +01:00
|
|
|
{
|
|
|
|
}
|
2017-12-03 17:58:18 +01:00
|
|
|
|
2019-05-12 13:54:22 +02:00
|
|
|
int QskShortcutQml::shortcutId() const
|
2017-12-06 17:01:10 +01:00
|
|
|
{
|
|
|
|
return m_data->id;
|
2017-12-03 17:58:18 +01:00
|
|
|
}
|
|
|
|
|
2019-05-12 13:54:22 +02:00
|
|
|
Qt::ShortcutContext QskShortcutQml::context() const
|
2017-12-03 17:58:18 +01:00
|
|
|
{
|
2017-12-06 17:01:10 +01:00
|
|
|
return m_data->isWindowContext
|
|
|
|
? Qt::WindowShortcut : Qt::ApplicationShortcut;
|
2017-12-05 13:10:50 +01:00
|
|
|
}
|
|
|
|
|
2019-05-12 13:54:22 +02:00
|
|
|
void QskShortcutQml::setContext( Qt::ShortcutContext context )
|
2017-12-05 13:10:50 +01:00
|
|
|
{
|
2018-08-03 08:15:28 +02:00
|
|
|
if ( context == Qt::ApplicationShortcut ||
|
|
|
|
context == Qt::WindowShortcut )
|
2017-12-05 17:40:21 +01:00
|
|
|
{
|
2017-12-06 17:01:10 +01:00
|
|
|
const bool isWindowContext = ( context == Qt::WindowShortcut );
|
2017-12-03 17:58:18 +01:00
|
|
|
|
2017-12-06 17:01:10 +01:00
|
|
|
if ( isWindowContext != m_data->isWindowContext )
|
2017-12-05 17:40:21 +01:00
|
|
|
{
|
2017-12-06 17:01:10 +01:00
|
|
|
m_data->isWindowContext = isWindowContext;
|
|
|
|
m_data->resetShortcut( this );
|
2017-12-05 13:10:50 +01:00
|
|
|
|
2017-12-06 17:01:10 +01:00
|
|
|
Q_EMIT contextChanged();
|
|
|
|
}
|
2017-12-05 13:10:50 +01:00
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2019-05-12 13:54:22 +02:00
|
|
|
void QskShortcutQml::setSequence( const QKeySequence& sequence )
|
2017-12-05 17:40:21 +01:00
|
|
|
{
|
2017-12-06 17:01:10 +01:00
|
|
|
if ( sequence != m_data->sequence )
|
2017-12-05 17:40:21 +01:00
|
|
|
{
|
2017-12-06 17:01:10 +01:00
|
|
|
m_data->sequence = sequence;
|
|
|
|
m_data->resetShortcut( this );
|
2017-12-05 17:40:21 +01:00
|
|
|
|
2017-12-06 17:01:10 +01:00
|
|
|
Q_EMIT sequenceChanged();
|
2017-12-05 17:40:21 +01:00
|
|
|
}
|
2017-12-06 17:01:10 +01:00
|
|
|
}
|
2017-12-05 17:40:21 +01:00
|
|
|
|
2019-05-12 13:54:22 +02:00
|
|
|
QKeySequence QskShortcutQml::sequence() const
|
2017-12-06 17:01:10 +01:00
|
|
|
{
|
|
|
|
return m_data->sequence;
|
|
|
|
}
|
2017-12-05 17:40:21 +01:00
|
|
|
|
2019-05-12 13:54:22 +02:00
|
|
|
void QskShortcutQml::setSequenceVariant( const QVariant& sequence )
|
2017-12-06 17:01:10 +01:00
|
|
|
{
|
2020-11-21 20:36:47 +01:00
|
|
|
if ( sequence.userType() == QVariant::Int )
|
2018-08-03 08:15:28 +02:00
|
|
|
setSequence( static_cast< QKeySequence::StandardKey >( sequence.toInt() ) );
|
2017-12-06 17:01:10 +01:00
|
|
|
else
|
|
|
|
setSequence( QKeySequence::fromString( sequence.toString() ) );
|
2017-12-05 17:40:21 +01:00
|
|
|
}
|
|
|
|
|
2019-05-12 13:54:22 +02:00
|
|
|
QVariant QskShortcutQml::sequenceVariant() const
|
2017-12-03 17:58:18 +01:00
|
|
|
{
|
2017-12-06 17:01:10 +01:00
|
|
|
return m_data->sequence.toString();
|
|
|
|
}
|
2017-12-05 17:40:21 +01:00
|
|
|
|
2019-05-12 13:54:22 +02:00
|
|
|
void QskShortcutQml::setEnabled( bool on )
|
2017-12-06 17:01:10 +01:00
|
|
|
{
|
|
|
|
if ( on != m_data->enabled )
|
2017-12-03 17:58:18 +01:00
|
|
|
{
|
2017-12-06 17:01:10 +01:00
|
|
|
m_data->enabled = on;
|
2017-12-05 13:10:50 +01:00
|
|
|
|
2017-12-06 17:01:10 +01:00
|
|
|
if ( m_data->id != 0 )
|
|
|
|
qskShortcutMap().setShortcutEnabled( on, m_data->id, this );
|
2017-12-03 17:58:18 +01:00
|
|
|
|
2017-12-06 17:01:10 +01:00
|
|
|
Q_EMIT enabledChanged();
|
2017-12-03 17:58:18 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-12 13:54:22 +02:00
|
|
|
bool QskShortcutQml::isEnabled() const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2017-12-06 17:01:10 +01:00
|
|
|
return m_data->enabled;
|
|
|
|
}
|
2017-12-05 13:10:50 +01:00
|
|
|
|
2019-05-12 13:54:22 +02:00
|
|
|
void QskShortcutQml::setAutoRepeat( bool on )
|
2017-12-06 17:01:10 +01:00
|
|
|
{
|
|
|
|
if ( on != m_data->autoRepeat )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2017-12-06 17:01:10 +01:00
|
|
|
m_data->autoRepeat = on;
|
2017-12-05 13:10:50 +01:00
|
|
|
|
2017-12-06 17:01:10 +01:00
|
|
|
if ( m_data->id != 0 )
|
|
|
|
qskShortcutMap().setShortcutEnabled( on, m_data->id, this );
|
2017-12-05 13:10:50 +01:00
|
|
|
|
2017-12-06 17:01:10 +01:00
|
|
|
Q_EMIT autoRepeatChanged();
|
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2019-05-12 13:54:22 +02:00
|
|
|
bool QskShortcutQml::autoRepeat() const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2017-12-06 17:01:10 +01:00
|
|
|
return m_data->autoRepeat;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2019-05-12 13:54:22 +02:00
|
|
|
bool QskShortcutQml::event( QEvent* event )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2017-12-06 17:01:10 +01:00
|
|
|
if ( event->type() == QEvent::Shortcut )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2017-12-06 17:01:10 +01:00
|
|
|
auto* shortcutEvent = static_cast< QShortcutEvent* >( event );
|
2017-12-05 13:10:50 +01:00
|
|
|
|
2017-12-06 17:01:10 +01:00
|
|
|
if ( shortcutEvent->shortcutId() == m_data->id )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2017-12-06 17:01:10 +01:00
|
|
|
if ( shortcutEvent->isAmbiguous() )
|
|
|
|
Q_EMIT activatedAmbiguously();
|
2017-12-03 17:58:18 +01:00
|
|
|
else
|
2017-12-06 17:01:10 +01:00
|
|
|
Q_EMIT activated();
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-12-06 17:01:10 +01:00
|
|
|
return true;
|
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-05-12 13:54:22 +02:00
|
|
|
bool QskShortcutQml::isFocusInScope() const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2017-12-06 17:01:10 +01:00
|
|
|
if ( !m_data->isWindowContext )
|
|
|
|
return true;
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-12-06 17:01:10 +01:00
|
|
|
const QQuickItem* contextItem = nullptr;
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2017-12-06 17:01:10 +01:00
|
|
|
if ( parent()->isWindowType() )
|
|
|
|
{
|
|
|
|
if ( auto window = qobject_cast< const QQuickWindow* >( parent() ) )
|
|
|
|
contextItem = window->contentItem();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
contextItem = qobject_cast< const QQuickItem* >( parent() );
|
|
|
|
}
|
2017-12-03 17:58:18 +01:00
|
|
|
|
2017-12-06 17:01:10 +01:00
|
|
|
if ( contextItem )
|
|
|
|
{
|
|
|
|
return QskShortcutMap::contextMatcher( contextItem, Qt::WindowShortcut );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
qWarning( "QskShortcut has no valid parent for Qt::WindowShortcut" );
|
|
|
|
return false;
|
|
|
|
}
|
2017-12-03 17:58:18 +01:00
|
|
|
}
|
|
|
|
|
2019-05-12 13:54:22 +02:00
|
|
|
void QskShortcutQml::classBegin()
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2017-12-06 17:01:10 +01:00
|
|
|
m_data->isComplete = false;
|
2017-12-03 17:58:18 +01:00
|
|
|
}
|
|
|
|
|
2019-05-12 13:54:22 +02:00
|
|
|
void QskShortcutQml::componentComplete()
|
2017-12-03 17:58:18 +01:00
|
|
|
{
|
2017-12-06 17:01:10 +01:00
|
|
|
if ( m_data->isComplete == false )
|
|
|
|
{
|
|
|
|
m_data->isComplete = true;
|
|
|
|
m_data->resetShortcut( this );
|
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
2017-12-05 17:40:21 +01:00
|
|
|
|
2019-05-12 13:54:22 +02:00
|
|
|
#include "moc_QskShortcutQml.cpp"
|