QskInputManager introduced
This commit is contained in:
parent
221b573287
commit
186b18587b
@ -4,8 +4,7 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "QskInputContext.h"
|
#include "QskInputContext.h"
|
||||||
#include "QskInputPanel.h"
|
#include "QskInputManager.h"
|
||||||
#include "QskInputEngine.h"
|
|
||||||
|
|
||||||
#include "QskLinearBox.h"
|
#include "QskLinearBox.h"
|
||||||
#include "QskDialog.h"
|
#include "QskDialog.h"
|
||||||
@ -69,22 +68,19 @@ class QskInputContext::PrivateData
|
|||||||
public:
|
public:
|
||||||
// item receiving the input
|
// item receiving the input
|
||||||
QPointer< QQuickItem > inputItem;
|
QPointer< QQuickItem > inputItem;
|
||||||
QPointer< QskInputPanel > inputPanel;
|
|
||||||
|
|
||||||
// popup or window embedding the panel
|
// popup or window embedding the panel
|
||||||
QskPopup* inputPopup = nullptr;
|
QskPopup* inputPopup = nullptr;
|
||||||
QskWindow* inputWindow = nullptr;
|
QskWindow* inputWindow = nullptr;
|
||||||
|
|
||||||
QskInputEngine* engine = nullptr;
|
QskInputManager* inputManager = nullptr;
|
||||||
|
|
||||||
bool isPredictorDirty = true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QskInputContext::QskInputContext():
|
QskInputContext::QskInputContext():
|
||||||
m_data( new PrivateData() )
|
m_data( new PrivateData() )
|
||||||
{
|
{
|
||||||
setObjectName( "InputContext" );
|
setObjectName( "InputContext" );
|
||||||
m_data->engine = new QskInputEngine( this );
|
m_data->inputManager = new QskInputManager( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
QskInputContext::~QskInputContext()
|
QskInputContext::~QskInputContext()
|
||||||
@ -96,25 +92,22 @@ QQuickItem* QskInputContext::inputItem() const
|
|||||||
return m_data->inputItem;
|
return m_data->inputItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
QskInputPanel* QskInputContext::inputPanel() const
|
QskControl* QskInputContext::inputPanel() const
|
||||||
{
|
{
|
||||||
if ( m_data->inputPanel == nullptr )
|
auto panel = m_data->inputManager->panel( true );
|
||||||
{
|
|
||||||
auto that = const_cast< QskInputContext* >( this );
|
|
||||||
|
|
||||||
auto panel = new QskInputPanel();
|
if ( panel->parent() != this )
|
||||||
panel->setParent( that );
|
{
|
||||||
|
panel->setParent( const_cast< QskInputContext* >( this ) );
|
||||||
|
|
||||||
connect( panel, &QQuickItem::visibleChanged,
|
connect( panel, &QQuickItem::visibleChanged,
|
||||||
this, &QskInputContext::activeChanged );
|
this, &QskInputContext::activeChanged, Qt::UniqueConnection );
|
||||||
|
|
||||||
connect( panel, &QskControl::localeChanged,
|
connect( panel, &QskControl::localeChanged,
|
||||||
this, &QskInputContext::updateLocale );
|
this, [] { qskSendToPlatformContext( QEvent::LocaleChange ); } );
|
||||||
|
|
||||||
m_data->inputPanel = panel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_data->inputPanel;
|
return panel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskInputContext::update( Qt::InputMethodQueries queries )
|
void QskInputContext::update( Qt::InputMethodQueries queries )
|
||||||
@ -131,8 +124,7 @@ void QskInputContext::update( Qt::InputMethodQueries queries )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( auto panel = inputPanel() )
|
m_data->inputManager->processInputMethodQueries( queries );
|
||||||
panel->processInputMethodQueries( queries );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QRectF QskInputContext::panelRect() const
|
QRectF QskInputContext::panelRect() const
|
||||||
@ -143,7 +135,7 @@ QRectF QskInputContext::panelRect() const
|
|||||||
return QRectF();
|
return QRectF();
|
||||||
}
|
}
|
||||||
|
|
||||||
QskPopup* QskInputContext::createEmbeddingPopup( QskInputPanel* panel )
|
QskPopup* QskInputContext::createEmbeddingPopup( QskControl* panel )
|
||||||
{
|
{
|
||||||
auto popup = new QskPopup();
|
auto popup = new QskPopup();
|
||||||
|
|
||||||
@ -154,24 +146,35 @@ QskPopup* QskInputContext::createEmbeddingPopup( QskInputPanel* panel )
|
|||||||
auto box = new QskLinearBox( popup );
|
auto box = new QskLinearBox( popup );
|
||||||
box->addItem( panel );
|
box->addItem( panel );
|
||||||
|
|
||||||
/*
|
const auto alignment =
|
||||||
When the panel has an input proxy ( usually a local text input )
|
m_data->inputManager->panelAlignment() & Qt::AlignVertical_Mask;
|
||||||
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();
|
|
||||||
|
|
||||||
popup->setOverlay( hasInputProxy );
|
popup->setOverlay( alignment == Qt::AlignVCenter );
|
||||||
|
|
||||||
if ( hasInputProxy )
|
switch( alignment )
|
||||||
|
{
|
||||||
|
case Qt::AlignTop:
|
||||||
|
{
|
||||||
|
box->setExtraSpacingAt( Qt::BottomEdge | Qt::LeftEdge | Qt::RightEdge );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Qt::AlignVCenter:
|
||||||
|
{
|
||||||
box->setMargins( QMarginsF( 5, 5, 5, 5 ) );
|
box->setMargins( QMarginsF( 5, 5, 5, 5 ) );
|
||||||
else
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Qt::AlignBottom:
|
||||||
|
default:
|
||||||
|
{
|
||||||
box->setExtraSpacingAt( Qt::TopEdge | Qt::LeftEdge | Qt::RightEdge );
|
box->setExtraSpacingAt( Qt::TopEdge | Qt::LeftEdge | Qt::RightEdge );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return popup;
|
return popup;
|
||||||
}
|
}
|
||||||
|
|
||||||
QskWindow* QskInputContext::createEmbeddingWindow( QskInputPanel* panel )
|
QskWindow* QskInputContext::createEmbeddingWindow( QskControl* panel )
|
||||||
{
|
{
|
||||||
auto window = new QskWindow();
|
auto window = new QskWindow();
|
||||||
|
|
||||||
@ -259,11 +262,7 @@ void QskInputContext::showPanel()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePredictor();
|
m_data->inputManager->attachInputItem( m_data->inputItem );
|
||||||
|
|
||||||
panel->setLocale( locale() );
|
|
||||||
panel->attachInputItem( m_data->inputItem );
|
|
||||||
panel->setEngine( m_data->engine );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskInputContext::hidePanel()
|
void QskInputContext::hidePanel()
|
||||||
@ -285,17 +284,13 @@ void QskInputContext::hidePanel()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( auto panel = inputPanel() )
|
if ( auto panel = m_data->inputManager->panel( false ) )
|
||||||
{
|
|
||||||
panel->setParentItem( nullptr );
|
panel->setParentItem( nullptr );
|
||||||
panel->attachInputItem( nullptr );
|
|
||||||
panel->setEngine( nullptr );
|
m_data->inputManager->attachInputItem( nullptr );
|
||||||
}
|
|
||||||
|
|
||||||
if ( m_data->inputPopup )
|
if ( m_data->inputPopup )
|
||||||
{
|
|
||||||
m_data->inputPopup->deleteLater();
|
m_data->inputPopup->deleteLater();
|
||||||
}
|
|
||||||
|
|
||||||
if ( m_data->inputWindow )
|
if ( m_data->inputWindow )
|
||||||
{
|
{
|
||||||
@ -341,28 +336,6 @@ QLocale QskInputContext::locale() const
|
|||||||
return QLocale();
|
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 )
|
void QskInputContext::setFocusObject( QObject* focusObject )
|
||||||
{
|
{
|
||||||
if ( m_data->inputItem == nullptr || m_data->inputItem == focusObject )
|
if ( m_data->inputItem == nullptr || m_data->inputItem == focusObject )
|
||||||
|
@ -12,7 +12,8 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
class QskTextPredictor;
|
class QskTextPredictor;
|
||||||
class QskInputPanel;
|
class QskControl;
|
||||||
|
class QskInputManager;
|
||||||
class QskPopup;
|
class QskPopup;
|
||||||
class QskWindow;
|
class QskWindow;
|
||||||
class QQuickItem;
|
class QQuickItem;
|
||||||
@ -27,19 +28,23 @@ public:
|
|||||||
QskInputContext();
|
QskInputContext();
|
||||||
virtual ~QskInputContext();
|
virtual ~QskInputContext();
|
||||||
|
|
||||||
virtual QRectF panelRect() const;
|
void setManager( QskInputManager* );
|
||||||
|
QskInputManager manager();
|
||||||
|
|
||||||
virtual void setActive( bool );
|
QRectF panelRect() const;
|
||||||
virtual bool isActive() const;
|
|
||||||
|
|
||||||
virtual QLocale locale() const;
|
void setActive( bool );
|
||||||
|
bool isActive() const;
|
||||||
|
|
||||||
virtual QQuickItem* inputItem() const;
|
QLocale locale() const;
|
||||||
virtual QskInputPanel* inputPanel() const;
|
|
||||||
|
QQuickItem* inputItem() const;
|
||||||
|
|
||||||
static QskInputContext* instance();
|
static QskInputContext* instance();
|
||||||
static void setInstance( QskInputContext* );
|
static void setInstance( QskInputContext* );
|
||||||
|
|
||||||
|
virtual QskTextPredictor* textPredictor( const QLocale& ) const;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void activeChanged();
|
void activeChanged();
|
||||||
void panelRectChanged();
|
void panelRectChanged();
|
||||||
@ -47,13 +52,13 @@ Q_SIGNALS:
|
|||||||
protected:
|
protected:
|
||||||
virtual bool eventFilter( QObject*, QEvent* ) override;
|
virtual bool eventFilter( QObject*, QEvent* ) override;
|
||||||
|
|
||||||
virtual QskPopup* createEmbeddingPopup( QskInputPanel* );
|
virtual QskPopup* createEmbeddingPopup( QskControl* );
|
||||||
virtual QskWindow* createEmbeddingWindow( QskInputPanel* );
|
virtual QskWindow* createEmbeddingWindow( QskControl* );
|
||||||
|
|
||||||
virtual void showPanel();
|
virtual void showPanel();
|
||||||
virtual void hidePanel();
|
virtual void hidePanel();
|
||||||
|
|
||||||
virtual QskTextPredictor* textPredictor( const QLocale& ) const;
|
QskControl* inputPanel() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class QskPlatformInputContext;
|
friend class QskPlatformInputContext;
|
||||||
@ -64,12 +69,8 @@ private:
|
|||||||
virtual void processClickAt( int cursorPosition );
|
virtual void processClickAt( int cursorPosition );
|
||||||
virtual void commitPrediction( bool );
|
virtual void commitPrediction( bool );
|
||||||
|
|
||||||
void updateLocale();
|
|
||||||
void updatePredictor();
|
|
||||||
|
|
||||||
class PrivateData;
|
class PrivateData;
|
||||||
std::unique_ptr< PrivateData > m_data;
|
std::unique_ptr< PrivateData > m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#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