QskInputManager introduced
This commit is contained in:
parent
221b573287
commit
186b18587b
@ -4,8 +4,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
#include "QskInputContext.h"
|
||||
#include "QskInputPanel.h"
|
||||
#include "QskInputEngine.h"
|
||||
#include "QskInputManager.h"
|
||||
|
||||
#include "QskLinearBox.h"
|
||||
#include "QskDialog.h"
|
||||
@ -69,22 +68,19 @@ class QskInputContext::PrivateData
|
||||
public:
|
||||
// item receiving the input
|
||||
QPointer< QQuickItem > inputItem;
|
||||
QPointer< QskInputPanel > inputPanel;
|
||||
|
||||
// popup or window embedding the panel
|
||||
QskPopup* inputPopup = nullptr;
|
||||
QskWindow* inputWindow = nullptr;
|
||||
|
||||
QskInputEngine* engine = nullptr;
|
||||
|
||||
bool isPredictorDirty = true;
|
||||
QskInputManager* inputManager = nullptr;
|
||||
};
|
||||
|
||||
QskInputContext::QskInputContext():
|
||||
m_data( new PrivateData() )
|
||||
{
|
||||
setObjectName( "InputContext" );
|
||||
m_data->engine = new QskInputEngine( this );
|
||||
m_data->inputManager = new QskInputManager( this );
|
||||
}
|
||||
|
||||
QskInputContext::~QskInputContext()
|
||||
@ -96,25 +92,22 @@ QQuickItem* QskInputContext::inputItem() const
|
||||
return m_data->inputItem;
|
||||
}
|
||||
|
||||
QskInputPanel* QskInputContext::inputPanel() const
|
||||
QskControl* QskInputContext::inputPanel() const
|
||||
{
|
||||
if ( m_data->inputPanel == nullptr )
|
||||
{
|
||||
auto that = const_cast< QskInputContext* >( this );
|
||||
auto panel = m_data->inputManager->panel( true );
|
||||
|
||||
auto panel = new QskInputPanel();
|
||||
panel->setParent( that );
|
||||
if ( panel->parent() != this )
|
||||
{
|
||||
panel->setParent( const_cast< QskInputContext* >( this ) );
|
||||
|
||||
connect( panel, &QQuickItem::visibleChanged,
|
||||
this, &QskInputContext::activeChanged );
|
||||
|
||||
connect( panel, &QskControl::localeChanged,
|
||||
this, &QskInputContext::updateLocale );
|
||||
this, &QskInputContext::activeChanged, Qt::UniqueConnection );
|
||||
|
||||
m_data->inputPanel = panel;
|
||||
connect( panel, &QskControl::localeChanged,
|
||||
this, [] { qskSendToPlatformContext( QEvent::LocaleChange ); } );
|
||||
}
|
||||
|
||||
return m_data->inputPanel;
|
||||
return panel;
|
||||
}
|
||||
|
||||
void QskInputContext::update( Qt::InputMethodQueries queries )
|
||||
@ -131,8 +124,7 @@ void QskInputContext::update( Qt::InputMethodQueries queries )
|
||||
}
|
||||
}
|
||||
|
||||
if ( auto panel = inputPanel() )
|
||||
panel->processInputMethodQueries( queries );
|
||||
m_data->inputManager->processInputMethodQueries( queries );
|
||||
}
|
||||
|
||||
QRectF QskInputContext::panelRect() const
|
||||
@ -143,7 +135,7 @@ QRectF QskInputContext::panelRect() const
|
||||
return QRectF();
|
||||
}
|
||||
|
||||
QskPopup* QskInputContext::createEmbeddingPopup( QskInputPanel* panel )
|
||||
QskPopup* QskInputContext::createEmbeddingPopup( QskControl* panel )
|
||||
{
|
||||
auto popup = new QskPopup();
|
||||
|
||||
@ -154,24 +146,35 @@ QskPopup* QskInputContext::createEmbeddingPopup( QskInputPanel* panel )
|
||||
auto box = new QskLinearBox( popup );
|
||||
box->addItem( panel );
|
||||
|
||||
/*
|
||||
When the panel has an input proxy ( usually a local text input )
|
||||
we don't need to see the input item and display the overlay
|
||||
and align in the center of the window.
|
||||
*/
|
||||
const bool hasInputProxy = panel->hasInputProxy();
|
||||
const auto alignment =
|
||||
m_data->inputManager->panelAlignment() & Qt::AlignVertical_Mask;
|
||||
|
||||
popup->setOverlay( hasInputProxy );
|
||||
popup->setOverlay( alignment == Qt::AlignVCenter );
|
||||
|
||||
if ( hasInputProxy )
|
||||
box->setMargins( QMarginsF( 5, 5, 5, 5 ) );
|
||||
else
|
||||
box->setExtraSpacingAt( Qt::TopEdge | Qt::LeftEdge | Qt::RightEdge );
|
||||
switch( alignment )
|
||||
{
|
||||
case Qt::AlignTop:
|
||||
{
|
||||
box->setExtraSpacingAt( Qt::BottomEdge | Qt::LeftEdge | Qt::RightEdge );
|
||||
break;
|
||||
}
|
||||
case Qt::AlignVCenter:
|
||||
{
|
||||
box->setMargins( QMarginsF( 5, 5, 5, 5 ) );
|
||||
break;
|
||||
}
|
||||
|
||||
case Qt::AlignBottom:
|
||||
default:
|
||||
{
|
||||
box->setExtraSpacingAt( Qt::TopEdge | Qt::LeftEdge | Qt::RightEdge );
|
||||
}
|
||||
}
|
||||
|
||||
return popup;
|
||||
}
|
||||
|
||||
QskWindow* QskInputContext::createEmbeddingWindow( QskInputPanel* panel )
|
||||
QskWindow* QskInputContext::createEmbeddingWindow( QskControl* panel )
|
||||
{
|
||||
auto window = new QskWindow();
|
||||
|
||||
@ -254,16 +257,12 @@ void QskInputContext::showPanel()
|
||||
popup->setVisible( true );
|
||||
popup->installEventFilter( this );
|
||||
}
|
||||
|
||||
|
||||
m_data->inputPopup = popup;
|
||||
}
|
||||
}
|
||||
|
||||
updatePredictor();
|
||||
|
||||
panel->setLocale( locale() );
|
||||
panel->attachInputItem( m_data->inputItem );
|
||||
panel->setEngine( m_data->engine );
|
||||
m_data->inputManager->attachInputItem( m_data->inputItem );
|
||||
}
|
||||
|
||||
void QskInputContext::hidePanel()
|
||||
@ -285,17 +284,13 @@ void QskInputContext::hidePanel()
|
||||
#endif
|
||||
}
|
||||
|
||||
if ( auto panel = inputPanel() )
|
||||
{
|
||||
if ( auto panel = m_data->inputManager->panel( false ) )
|
||||
panel->setParentItem( nullptr );
|
||||
panel->attachInputItem( nullptr );
|
||||
panel->setEngine( nullptr );
|
||||
}
|
||||
|
||||
m_data->inputManager->attachInputItem( nullptr );
|
||||
|
||||
if ( m_data->inputPopup )
|
||||
{
|
||||
m_data->inputPopup->deleteLater();
|
||||
}
|
||||
|
||||
if ( m_data->inputWindow )
|
||||
{
|
||||
@ -341,28 +336,6 @@ QLocale QskInputContext::locale() const
|
||||
return QLocale();
|
||||
}
|
||||
|
||||
void QskInputContext::updateLocale()
|
||||
{
|
||||
m_data->isPredictorDirty = true;
|
||||
|
||||
if ( isActive() )
|
||||
updatePredictor();
|
||||
|
||||
qskSendToPlatformContext( QEvent::LocaleChange );
|
||||
}
|
||||
|
||||
void QskInputContext::updatePredictor()
|
||||
{
|
||||
if ( m_data->isPredictorDirty )
|
||||
{
|
||||
if ( m_data->engine )
|
||||
{
|
||||
m_data->engine->setPredictor( textPredictor( locale() ) );
|
||||
m_data->isPredictorDirty = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QskInputContext::setFocusObject( QObject* focusObject )
|
||||
{
|
||||
if ( m_data->inputItem == nullptr || m_data->inputItem == focusObject )
|
||||
|
@ -12,7 +12,8 @@
|
||||
#include <memory>
|
||||
|
||||
class QskTextPredictor;
|
||||
class QskInputPanel;
|
||||
class QskControl;
|
||||
class QskInputManager;
|
||||
class QskPopup;
|
||||
class QskWindow;
|
||||
class QQuickItem;
|
||||
@ -27,19 +28,23 @@ public:
|
||||
QskInputContext();
|
||||
virtual ~QskInputContext();
|
||||
|
||||
virtual QRectF panelRect() const;
|
||||
void setManager( QskInputManager* );
|
||||
QskInputManager manager();
|
||||
|
||||
virtual void setActive( bool );
|
||||
virtual bool isActive() const;
|
||||
QRectF panelRect() const;
|
||||
|
||||
virtual QLocale locale() const;
|
||||
void setActive( bool );
|
||||
bool isActive() const;
|
||||
|
||||
virtual QQuickItem* inputItem() const;
|
||||
virtual QskInputPanel* inputPanel() const;
|
||||
QLocale locale() const;
|
||||
|
||||
QQuickItem* inputItem() const;
|
||||
|
||||
static QskInputContext* instance();
|
||||
static void setInstance( QskInputContext* );
|
||||
|
||||
virtual QskTextPredictor* textPredictor( const QLocale& ) const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void activeChanged();
|
||||
void panelRectChanged();
|
||||
@ -47,13 +52,13 @@ Q_SIGNALS:
|
||||
protected:
|
||||
virtual bool eventFilter( QObject*, QEvent* ) override;
|
||||
|
||||
virtual QskPopup* createEmbeddingPopup( QskInputPanel* );
|
||||
virtual QskWindow* createEmbeddingWindow( QskInputPanel* );
|
||||
virtual QskPopup* createEmbeddingPopup( QskControl* );
|
||||
virtual QskWindow* createEmbeddingWindow( QskControl* );
|
||||
|
||||
virtual void showPanel();
|
||||
virtual void hidePanel();
|
||||
|
||||
virtual QskTextPredictor* textPredictor( const QLocale& ) const;
|
||||
QskControl* inputPanel() const;
|
||||
|
||||
private:
|
||||
friend class QskPlatformInputContext;
|
||||
@ -64,12 +69,8 @@ private:
|
||||
virtual void processClickAt( int cursorPosition );
|
||||
virtual void commitPrediction( bool );
|
||||
|
||||
void updateLocale();
|
||||
void updatePredictor();
|
||||
|
||||
class PrivateData;
|
||||
std::unique_ptr< PrivateData > m_data;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
138
src/inputpanel/QskInputManager.cpp
Normal file
138
src/inputpanel/QskInputManager.cpp
Normal file
@ -0,0 +1,138 @@
|
||||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* This file may be used under the terms of the QSkinny License, Version 1.0
|
||||
*****************************************************************************/
|
||||
|
||||
#include "QskInputManager.h"
|
||||
#include "QskInputPanel.h"
|
||||
#include "QskInputEngine.h"
|
||||
#include "QskInputContext.h"
|
||||
#include <QPointer>
|
||||
|
||||
class QskInputManager::PrivateData
|
||||
{
|
||||
public:
|
||||
QPointer< QskInputEngine > engine;
|
||||
QPointer< QskControl > panel;
|
||||
|
||||
QLocale predictorLocale;
|
||||
};
|
||||
|
||||
QskInputManager::QskInputManager( QObject* parent ):
|
||||
Inherited( parent ),
|
||||
m_data( new PrivateData() )
|
||||
{
|
||||
}
|
||||
|
||||
QskInputManager::~QskInputManager()
|
||||
{
|
||||
}
|
||||
|
||||
void QskInputManager::attachInputItem( QQuickItem* item )
|
||||
{
|
||||
auto panel = qobject_cast< QskInputPanel* >( m_data->panel );
|
||||
if ( panel == nullptr )
|
||||
return;
|
||||
|
||||
if ( item )
|
||||
{
|
||||
auto context = QskInputContext::instance();
|
||||
const auto locale = context->locale();
|
||||
|
||||
updateEngine( locale );
|
||||
|
||||
panel->setEngine( m_data->engine );
|
||||
panel->setLocale( locale );
|
||||
panel->attachInputItem( item );
|
||||
}
|
||||
else
|
||||
{
|
||||
panel->setEngine( nullptr );
|
||||
panel->attachInputItem( nullptr );
|
||||
}
|
||||
}
|
||||
|
||||
void QskInputManager::processInputMethodQueries(
|
||||
Qt::InputMethodQueries queries )
|
||||
{
|
||||
if ( auto panel = qobject_cast< QskInputPanel* >( m_data->panel ) )
|
||||
panel->processInputMethodQueries( queries );
|
||||
}
|
||||
|
||||
QskControl* QskInputManager::panel( bool doCreate )
|
||||
{
|
||||
if ( m_data->panel == nullptr && doCreate )
|
||||
{
|
||||
m_data->panel = createPanel();
|
||||
|
||||
connect( m_data->panel, &QskControl::localeChanged,
|
||||
this, &QskInputManager::updatePredictor, Qt::UniqueConnection );
|
||||
}
|
||||
|
||||
return m_data->panel;
|
||||
}
|
||||
|
||||
Qt::Alignment QskInputManager::panelAlignment() const
|
||||
{
|
||||
if ( auto panel = qobject_cast< QskInputPanel* >( m_data->panel ) )
|
||||
{
|
||||
if ( panel->hasInputProxy() )
|
||||
{
|
||||
/*
|
||||
When the panel has an input proxy we don't need to see
|
||||
the input item and can put the panel in the center
|
||||
*/
|
||||
|
||||
return Qt::AlignVCenter;
|
||||
}
|
||||
}
|
||||
|
||||
return Qt::AlignBottom;
|
||||
}
|
||||
|
||||
QskControl* QskInputManager::createPanel()
|
||||
{
|
||||
return new QskInputPanel();
|
||||
}
|
||||
|
||||
QskInputEngine* QskInputManager::createEngine()
|
||||
{
|
||||
return new QskInputEngine();
|
||||
}
|
||||
|
||||
void QskInputManager::updateEngine( const QLocale& locale )
|
||||
{
|
||||
auto context = QskInputContext::instance();
|
||||
|
||||
if ( m_data->engine == nullptr)
|
||||
{
|
||||
auto engine = createEngine();
|
||||
if ( engine->parent() == nullptr )
|
||||
engine->setParent( this );
|
||||
|
||||
m_data->predictorLocale = locale;
|
||||
engine->setPredictor( context->textPredictor( locale ) );
|
||||
|
||||
m_data->engine = engine;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_data->predictorLocale != locale )
|
||||
{
|
||||
m_data->predictorLocale = locale;
|
||||
m_data->engine->setPredictor( context->textPredictor( locale ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QskInputManager::updatePredictor()
|
||||
{
|
||||
if ( m_data->panel && m_data->engine )
|
||||
{
|
||||
auto context = QskInputContext::instance();
|
||||
const auto locale = context->locale();
|
||||
|
||||
if ( m_data->predictorLocale != locale )
|
||||
m_data->engine->setPredictor( context->textPredictor( locale ) );
|
||||
}
|
||||
}
|
46
src/inputpanel/QskInputManager.h
Normal file
46
src/inputpanel/QskInputManager.h
Normal file
@ -0,0 +1,46 @@
|
||||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* This file may be used under the terms of the QSkinny License, Version 1.0
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QSK_INPUT_MANAGER_H
|
||||
#define QSK_INPUT_MANAGER_H
|
||||
|
||||
#include "QskGlobal.h"
|
||||
#include <QObject>
|
||||
#include <memory>
|
||||
|
||||
class QskInputEngine;
|
||||
class QskControl;
|
||||
class QQuickItem;
|
||||
class QLocale;
|
||||
|
||||
class QSK_EXPORT QskInputManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
using Inherited = QObject;
|
||||
|
||||
public:
|
||||
QskInputManager( QObject* parent = nullptr );
|
||||
virtual ~QskInputManager() override;
|
||||
|
||||
virtual void attachInputItem( QQuickItem* );
|
||||
virtual void processInputMethodQueries( Qt::InputMethodQueries );
|
||||
|
||||
QskControl* panel( bool doCreate );
|
||||
virtual Qt::Alignment panelAlignment() const;
|
||||
|
||||
protected:
|
||||
virtual QskControl* createPanel();
|
||||
virtual QskInputEngine* createEngine();
|
||||
|
||||
void updatePredictor();
|
||||
void updateEngine( const QLocale& );
|
||||
|
||||
private:
|
||||
class PrivateData;
|
||||
std::unique_ptr< PrivateData > m_data;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user