qskinny/inputcontext/QskInputContextPlugin.cpp

283 lines
6.4 KiB
C++

/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#include <qpa/qplatforminputcontextplugin_p.h>
#include <qpa/qplatforminputcontext.h>
#include "QskInputContext.h"
#define HUNSPELL 0
#if HUNSPELL
#include "QskHunspellTextPredictor.h"
#endif
#include <QLocale>
#include <QRectF>
#include <QEvent>
namespace
{
class InputContext : public QskInputContext
{
public:
virtual QskTextPredictor* textPredictor( const QLocale& locale ) const
{
#if HUNSPELL
/*
For the moment we manage the text prediction in the context
plugin - but of course it has to be moved somewhere else
*/
if ( locale.language() == QLocale::English )
return new QskHunspellTextPredictor();
#endif
return QskInputContext::textPredictor( locale );
}
};
}
/*
QPlatformInputContext is no stable public API.
So we forward everything to QskInputContext
*/
class QskPlatformInputContext final : public QPlatformInputContext
{
Q_OBJECT
using Inherited = QPlatformInputContext;
public:
QskPlatformInputContext();
virtual ~QskPlatformInputContext() = default;
virtual bool isValid() const override;
virtual bool hasCapability( Capability ) const override;
virtual void update( Qt::InputMethodQueries ) override;
virtual void invokeAction( QInputMethod::Action, int ) override;
virtual QRectF keyboardRect() const override;
virtual bool isAnimating() const override;
virtual void showInputPanel() override;
virtual void hideInputPanel() override;
virtual bool isInputPanelVisible() const override;
virtual void reset() override;
virtual void commit() override;
virtual void setFocusObject( QObject* ) override;
virtual QLocale locale() const override;
virtual Qt::LayoutDirection inputDirection() const override;
virtual bool filterEvent( const QEvent* ) override;
Q_INVOKABLE QQuickItem* inputItem();
protected:
virtual bool event( QEvent* ) override;
private:
void updateContext();
void updateLocale();
QLocale m_locale;
QPointer< QskInputContext > m_context;
};
QskPlatformInputContext::QskPlatformInputContext()
{
auto context = QskInputContext::instance();
if ( context == nullptr )
{
context = new InputContext();
QskInputContext::setInstance( context );
}
updateContext();
updateLocale();
}
void QskPlatformInputContext::updateContext()
{
if ( m_context )
m_context->disconnect( this );
m_context = QskInputContext::instance();
if ( m_context )
{
connect( m_context, &QskInputContext::activeChanged,
this, &QPlatformInputContext::emitInputPanelVisibleChanged );
connect( m_context, &QskInputContext::panelRectChanged,
this, &QPlatformInputContext::emitKeyboardRectChanged );
}
}
void QskPlatformInputContext::updateLocale()
{
if ( m_context )
{
const auto oldLocale = m_locale;
m_locale = m_context->locale();
if ( oldLocale != m_locale )
emitLocaleChanged();
if ( m_locale.textDirection() != oldLocale.textDirection() )
emitInputDirectionChanged( m_locale.textDirection() );
}
}
bool QskPlatformInputContext::isValid() const
{
return true;
}
bool QskPlatformInputContext::hasCapability( Capability ) const
{
// what is QPlatformInputContext::HiddenTextCapability ???
return true;
}
void QskPlatformInputContext::update( Qt::InputMethodQueries queries )
{
if ( m_context )
m_context->update( queries );
}
void QskPlatformInputContext::invokeAction(
QInputMethod::Action action, int cursorPosition )
{
if ( m_context )
{
if ( action == QInputMethod::Click )
m_context->processClickAt( cursorPosition );
}
}
QRectF QskPlatformInputContext::keyboardRect() const
{
if ( m_context )
return m_context->panelRect();
return QRectF();
}
bool QskPlatformInputContext::isAnimating() const
{
// who is interested in this ?
// also: emitAnimatingChanged
return false;
}
void QskPlatformInputContext::showInputPanel()
{
if ( m_context )
m_context->setActive( true );
}
void QskPlatformInputContext::hideInputPanel()
{
if ( m_context )
m_context->setActive( false );
}
bool QskPlatformInputContext::isInputPanelVisible() const
{
if ( m_context )
return m_context->isActive();
return false;
}
void QskPlatformInputContext::reset()
{
if ( m_context )
m_context->commitPrediction( false );
}
void QskPlatformInputContext::commit()
{
if ( m_context )
m_context->commitPrediction( true );
}
void QskPlatformInputContext::setFocusObject( QObject* object )
{
if ( m_context )
m_context->setFocusObject( object );
}
QLocale QskPlatformInputContext::locale() const
{
return m_locale;
}
Qt::LayoutDirection QskPlatformInputContext::inputDirection() const
{
return m_locale.textDirection();
}
bool QskPlatformInputContext::filterEvent( const QEvent* )
{
// called from QXcbKeyboard, but what about other platforms
return false;
}
QQuickItem* QskPlatformInputContext::inputItem()
{
if ( m_context )
return m_context->inputItem();
return nullptr;
}
bool QskPlatformInputContext::event( QEvent* event )
{
switch( event->type() )
{
case QEvent::LocaleChange:
{
updateLocale();
break;
}
case QEvent::PlatformPanel:
{
updateContext();
break;
}
default:
break;
}
return Inherited::event( event );
}
class QskInputContextPlugin final : public QPlatformInputContextPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA( IID QPlatformInputContextFactoryInterface_iid FILE "metadata.json" )
public:
virtual QPlatformInputContext* create(
const QString& system, const QStringList& ) override
{
if ( system.compare( QStringLiteral( "skinny" ), Qt::CaseInsensitive ) == 0 )
{
auto context = new QskPlatformInputContext();
return context;
}
return nullptr;
}
};
#include "QskInputContextPlugin.moc"