input panel stuff
This commit is contained in:
parent
897f6c520b
commit
d947fb3999
@ -14,17 +14,30 @@
|
|||||||
#include <QskSetup.h>
|
#include <QskSetup.h>
|
||||||
|
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
|
#include <QHash>
|
||||||
|
#include <QPointer>
|
||||||
|
|
||||||
|
class QskInputContext::PrivateData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QPointer< QQuickItem > inputItem;
|
||||||
|
QPointer< QskVirtualKeyboard > inputPanel;
|
||||||
|
QskInputCompositionModel* compositionModel;
|
||||||
|
QHash< QLocale, QskInputCompositionModel* > inputModels;
|
||||||
|
};
|
||||||
|
|
||||||
QskInputContext::QskInputContext() :
|
QskInputContext::QskInputContext() :
|
||||||
Inherited(),
|
m_data( new PrivateData() )
|
||||||
m_defaultInputCompositionModel( new QskInputCompositionModel )
|
|
||||||
{
|
{
|
||||||
|
m_data->compositionModel = new QskInputCompositionModel();
|
||||||
|
|
||||||
connect( qskSetup, &QskSetup::inputPanelChanged,
|
connect( qskSetup, &QskSetup::inputPanelChanged,
|
||||||
this, &QskInputContext::setInputPanel );
|
this, &QskInputContext::setInputPanel );
|
||||||
|
|
||||||
setInputPanel( qskSetup->inputPanel() );
|
setInputPanel( qskSetup->inputPanel() );
|
||||||
|
|
||||||
QskPinyinCompositionModel* pinyinModel = new QskPinyinCompositionModel;
|
QskPinyinCompositionModel* pinyinModel = new QskPinyinCompositionModel;
|
||||||
// For input methods outside skinny, call QskInputPanel::registerCompositionModelForLocale()
|
// see also: QskVirtualKeyboard::registerCompositionModelForLocale()
|
||||||
inputMethodRegistered( QLocale::Chinese, pinyinModel );
|
inputMethodRegistered( QLocale::Chinese, pinyinModel );
|
||||||
|
|
||||||
// We could connect candidatesChanged() here, but we don't emit
|
// We could connect candidatesChanged() here, but we don't emit
|
||||||
@ -33,13 +46,10 @@ QskInputContext::QskInputContext():
|
|||||||
|
|
||||||
QskInputContext::~QskInputContext()
|
QskInputContext::~QskInputContext()
|
||||||
{
|
{
|
||||||
if ( m_inputPanel )
|
if ( m_data->inputPanel )
|
||||||
delete m_inputPanel;
|
delete m_data->inputPanel;
|
||||||
|
|
||||||
for( int a = 0; a < m_inputModels.values().count(); a++ )
|
qDeleteAll( m_data->inputModels );
|
||||||
{
|
|
||||||
delete m_inputModels.values()[a];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QskInputContext::isValid() const
|
bool QskInputContext::isValid() const
|
||||||
@ -49,11 +59,11 @@ bool QskInputContext::isValid() const
|
|||||||
|
|
||||||
void QskInputContext::update( Qt::InputMethodQueries queries )
|
void QskInputContext::update( Qt::InputMethodQueries queries )
|
||||||
{
|
{
|
||||||
if ( !m_inputItem )
|
if ( !m_data->inputItem )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QInputMethodQueryEvent queryEvent( queries );
|
QInputMethodQueryEvent queryEvent( queries );
|
||||||
if ( !QCoreApplication::sendEvent( m_inputItem, &queryEvent ) )
|
if ( !QCoreApplication::sendEvent( m_data->inputItem, &queryEvent ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Qt::ImCursorRectangle
|
// Qt::ImCursorRectangle
|
||||||
@ -98,26 +108,24 @@ void QskInputContext::update( Qt::InputMethodQueries queries )
|
|||||||
{
|
{
|
||||||
const auto locale = queryEvent.value( Qt::ImPreferredLanguage ).toLocale();
|
const auto locale = queryEvent.value( Qt::ImPreferredLanguage ).toLocale();
|
||||||
|
|
||||||
auto oldModel = currentInputCompositionModel();
|
auto oldModel = compositionModel();
|
||||||
|
|
||||||
if( m_inputPanel )
|
if( m_data->inputPanel )
|
||||||
m_inputPanel->setLocale( locale );
|
m_data->inputPanel->setLocale( locale );
|
||||||
|
|
||||||
auto newModel = currentInputCompositionModel();
|
auto newModel = compositionModel();
|
||||||
|
|
||||||
bool modelChanged = ( oldModel != newModel );
|
if( oldModel != newModel )
|
||||||
|
|
||||||
if( modelChanged )
|
|
||||||
{
|
{
|
||||||
if( m_inputPanel )
|
if( m_data->inputPanel )
|
||||||
{
|
{
|
||||||
m_inputPanel->setCandidateBarVisible( newModel->supportsSuggestions() );
|
m_data->inputPanel->setCandidateBarVisible( newModel->supportsSuggestions() );
|
||||||
m_inputPanel->disconnect( oldModel );
|
m_data->inputPanel->disconnect( oldModel );
|
||||||
QObject::connect(
|
|
||||||
newModel, &QskInputCompositionModel::groupsChanged,
|
connect( newModel, &QskInputCompositionModel::groupsChanged,
|
||||||
m_inputPanel.data(), &QskVirtualKeyboard::setPreeditGroups );
|
m_data->inputPanel.data(), &QskVirtualKeyboard::setPreeditGroups );
|
||||||
QObject::connect(
|
|
||||||
newModel, &QskInputCompositionModel::candidatesChanged,
|
connect( newModel, &QskInputCompositionModel::candidatesChanged,
|
||||||
this, &QskInputContext::handleCandidatesChanged );
|
this, &QskInputContext::handleCandidatesChanged );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,10 +139,10 @@ void QskInputContext::update( Qt::InputMethodQueries queries )
|
|||||||
|
|
||||||
QRectF QskInputContext::keyboardRect() const
|
QRectF QskInputContext::keyboardRect() const
|
||||||
{
|
{
|
||||||
if ( m_inputPanel
|
if ( m_data->inputPanel
|
||||||
&& QskDialog::instance()->policy() != QskDialog::TopLevelWindow )
|
&& QskDialog::instance()->policy() != QskDialog::TopLevelWindow )
|
||||||
{
|
{
|
||||||
return m_inputPanel->geometry();
|
return m_data->inputPanel->geometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Inherited::keyboardRect();
|
return Inherited::keyboardRect();
|
||||||
@ -147,16 +155,16 @@ bool QskInputContext::isAnimating() const
|
|||||||
|
|
||||||
void QskInputContext::showInputPanel()
|
void QskInputContext::showInputPanel()
|
||||||
{
|
{
|
||||||
if ( !m_inputPanel )
|
if ( !m_data->inputPanel )
|
||||||
{
|
{
|
||||||
setInputPanel( new QskVirtualKeyboard );
|
setInputPanel( new QskVirtualKeyboard() );
|
||||||
|
|
||||||
if ( QskDialog::instance()->policy() == QskDialog::TopLevelWindow )
|
if ( QskDialog::instance()->policy() == QskDialog::TopLevelWindow )
|
||||||
{
|
{
|
||||||
auto window = new QskWindow;
|
auto window = new QskWindow;
|
||||||
window->setFlags( Qt::Tool | Qt::WindowDoesNotAcceptFocus );
|
window->setFlags( Qt::Tool | Qt::WindowDoesNotAcceptFocus );
|
||||||
window->resize( 800, 240 ); // ### what size?
|
window->resize( 800, 240 ); // ### what size?
|
||||||
m_inputPanel->setParentItem( window->contentItem() );
|
m_data->inputPanel->setParentItem( window->contentItem() );
|
||||||
connect( window, &QskWindow::visibleChanged,
|
connect( window, &QskWindow::visibleChanged,
|
||||||
this, &QskInputContext::emitInputPanelVisibleChanged );
|
this, &QskInputContext::emitInputPanelVisibleChanged );
|
||||||
}
|
}
|
||||||
@ -165,62 +173,62 @@ void QskInputContext::showInputPanel()
|
|||||||
auto window = qobject_cast< QQuickWindow* >( QGuiApplication::focusWindow() );
|
auto window = qobject_cast< QQuickWindow* >( QGuiApplication::focusWindow() );
|
||||||
if ( window )
|
if ( window )
|
||||||
{
|
{
|
||||||
m_inputPanel->setParentItem( window->contentItem() );
|
m_data->inputPanel->setParentItem( window->contentItem() );
|
||||||
m_inputPanel->setSize( window->size() );
|
m_data->inputPanel->setSize( window->size() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto window = m_inputPanel->window();
|
auto window = m_data->inputPanel->window();
|
||||||
if ( window && window != QGuiApplication::focusWindow() )
|
if ( window && window != QGuiApplication::focusWindow() )
|
||||||
window->show();
|
window->show();
|
||||||
else
|
else
|
||||||
m_inputPanel->setVisible( true );
|
m_data->inputPanel->setVisible( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskInputContext::hideInputPanel()
|
void QskInputContext::hideInputPanel()
|
||||||
{
|
{
|
||||||
if ( !m_inputPanel )
|
if ( !m_data->inputPanel )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto window = m_inputPanel->window();
|
auto window = m_data->inputPanel->window();
|
||||||
if ( window && window != QGuiApplication::focusWindow() )
|
if ( window && window != QGuiApplication::focusWindow() )
|
||||||
window->hide();
|
window->hide();
|
||||||
else
|
else
|
||||||
m_inputPanel->setVisible( false );
|
m_data->inputPanel->setVisible( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QskInputContext::isInputPanelVisible() const
|
bool QskInputContext::isInputPanelVisible() const
|
||||||
{
|
{
|
||||||
return m_inputPanel && m_inputPanel->isVisible()
|
auto panel = m_data->inputPanel;
|
||||||
&& m_inputPanel->window() && m_inputPanel->window()->isVisible();
|
return panel && panel->isVisible()
|
||||||
|
&& panel->window() && panel->window()->isVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
QLocale QskInputContext::locale() const
|
QLocale QskInputContext::locale() const
|
||||||
{
|
{
|
||||||
return m_inputPanel ? m_inputPanel->locale() : QLocale();
|
return m_data->inputPanel ? m_data->inputPanel->locale() : QLocale();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskInputContext::setFocusObject( QObject* focusObject )
|
void QskInputContext::setFocusObject( QObject* focusObject )
|
||||||
{
|
{
|
||||||
m_focusObject = focusObject;
|
if ( focusObject == nullptr )
|
||||||
if ( !m_focusObject )
|
|
||||||
{
|
{
|
||||||
m_inputItem = nullptr;
|
m_data->inputItem = nullptr;
|
||||||
currentInputCompositionModel()->setInputItem( nullptr );
|
compositionModel()->setInputItem( nullptr );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool inputItemChanged = false;
|
bool inputItemChanged = false;
|
||||||
|
|
||||||
auto focusQuickItem = qobject_cast< QQuickItem* >( focusObject );
|
auto focusItem = qobject_cast< QQuickItem* >( focusObject );
|
||||||
if( focusQuickItem )
|
if( focusItem )
|
||||||
{
|
{
|
||||||
// Do not change the input item when panel buttons get the focus:
|
// Do not change the input item when panel buttons get the focus:
|
||||||
if( qskNearestFocusScope( focusQuickItem ) != m_inputPanel )
|
if( qskNearestFocusScope( focusItem ) != m_data->inputPanel )
|
||||||
{
|
{
|
||||||
m_inputItem = focusQuickItem;
|
m_data->inputItem = focusItem;
|
||||||
currentInputCompositionModel()->setInputItem( m_inputItem ); // ### use a signal/slot connection
|
compositionModel()->setInputItem( focusItem );
|
||||||
inputItemChanged = true;
|
inputItemChanged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -228,7 +236,7 @@ void QskInputContext::setFocusObject( QObject* focusObject )
|
|||||||
if( inputItemChanged )
|
if( inputItemChanged )
|
||||||
{
|
{
|
||||||
QInputMethodQueryEvent queryEvent( Qt::ImEnabled );
|
QInputMethodQueryEvent queryEvent( Qt::ImEnabled );
|
||||||
if ( !QCoreApplication::sendEvent( m_inputItem, &queryEvent ) )
|
if ( !QCoreApplication::sendEvent( m_data->inputItem, &queryEvent ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ( !queryEvent.value( Qt::ImEnabled ).toBool() )
|
if ( !queryEvent.value( Qt::ImEnabled ).toBool() )
|
||||||
@ -241,56 +249,46 @@ void QskInputContext::setFocusObject( QObject* focusObject )
|
|||||||
update( Qt::InputMethodQuery( Qt::ImQueryAll & ~Qt::ImEnabled ) );
|
update( Qt::InputMethodQuery( Qt::ImQueryAll & ~Qt::ImEnabled ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskInputContext::inputMethodRegistered( const QLocale& locale, QskInputCompositionModel* model )
|
void QskInputContext::inputMethodRegistered(
|
||||||
{
|
const QLocale& locale, QskInputCompositionModel* model )
|
||||||
auto oldModel = m_inputModels.value( locale, nullptr );
|
|
||||||
|
|
||||||
if( oldModel != nullptr )
|
|
||||||
{
|
{
|
||||||
|
if ( auto oldModel = m_data->inputModels.value( locale, nullptr ) )
|
||||||
oldModel->deleteLater();
|
oldModel->deleteLater();
|
||||||
|
|
||||||
|
m_data->inputModels.insert( locale, model );
|
||||||
}
|
}
|
||||||
|
|
||||||
m_inputModels.insert( locale, model );
|
QskInputCompositionModel* QskInputContext::compositionModel() const
|
||||||
}
|
|
||||||
|
|
||||||
QskInputCompositionModel* QskInputContext::compositionModelForLocale( const QLocale& locale ) const
|
|
||||||
{
|
{
|
||||||
return m_inputModels.value( locale, m_defaultInputCompositionModel );
|
return m_data->inputModels.value( locale(), m_data->compositionModel );
|
||||||
}
|
|
||||||
|
|
||||||
QskInputCompositionModel* QskInputContext::currentInputCompositionModel() const
|
|
||||||
{
|
|
||||||
return m_inputModels.value( locale(), m_defaultInputCompositionModel );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskInputContext::resetCandidates()
|
|
||||||
{
|
|
||||||
m_inputPanel->setPreeditCandidates( {} );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskInputContext::invokeAction( QInputMethod::Action action, int cursorPosition )
|
void QskInputContext::invokeAction( QInputMethod::Action action, int cursorPosition )
|
||||||
{
|
{
|
||||||
Q_UNUSED( cursorPosition );
|
auto model = compositionModel();
|
||||||
|
|
||||||
if ( !m_inputPanel )
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch ( static_cast< QskVirtualKeyboard::Action >( action ) )
|
switch ( static_cast< QskVirtualKeyboard::Action >( action ) )
|
||||||
{
|
{
|
||||||
case QskVirtualKeyboard::Compose:
|
case QskVirtualKeyboard::Compose:
|
||||||
currentInputCompositionModel()->composeKey( static_cast< Qt::Key >( cursorPosition ) );
|
{
|
||||||
|
model->composeKey( static_cast< Qt::Key >( cursorPosition ) );
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case QskVirtualKeyboard::SelectGroup:
|
case QskVirtualKeyboard::SelectGroup:
|
||||||
currentInputCompositionModel()->setGroupIndex( cursorPosition );
|
{
|
||||||
|
model->setGroupIndex( cursorPosition );
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case QskVirtualKeyboard::SelectCandidate:
|
case QskVirtualKeyboard::SelectCandidate:
|
||||||
currentInputCompositionModel()->commitCandidate( cursorPosition );
|
{
|
||||||
resetCandidates();
|
model->commitCandidate( cursorPosition );
|
||||||
|
if ( m_data->inputPanel )
|
||||||
|
m_data->inputPanel->setPreeditCandidates( QVector< QString >() );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QskInputContext::emitAnimatingChanged()
|
void QskInputContext::emitAnimatingChanged()
|
||||||
{
|
{
|
||||||
@ -299,32 +297,32 @@ void QskInputContext::emitAnimatingChanged()
|
|||||||
|
|
||||||
void QskInputContext::handleCandidatesChanged()
|
void QskInputContext::handleCandidatesChanged()
|
||||||
{
|
{
|
||||||
QVector< QString > candidates( currentInputCompositionModel()->candidateCount() );
|
const auto model = compositionModel();
|
||||||
|
|
||||||
|
QVector< QString > candidates( model->candidateCount() );
|
||||||
|
|
||||||
for( int i = 0; i < candidates.length(); ++i )
|
for( int i = 0; i < candidates.length(); ++i )
|
||||||
{
|
candidates[i] = model->candidate( i );
|
||||||
candidates[i] = currentInputCompositionModel()->candidate( i );
|
|
||||||
}
|
|
||||||
|
|
||||||
m_inputPanel->setPreeditCandidates( candidates );
|
m_data->inputPanel->setPreeditCandidates( candidates );
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskInputContext::setInputPanel( QskVirtualKeyboard* inputPanel )
|
void QskInputContext::setInputPanel( QskVirtualKeyboard* inputPanel )
|
||||||
{
|
{
|
||||||
if ( m_inputPanel == inputPanel )
|
if ( m_data->inputPanel == inputPanel )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto compositionModel = currentInputCompositionModel();
|
auto model = compositionModel();
|
||||||
|
|
||||||
if ( m_inputPanel )
|
if ( m_data->inputPanel )
|
||||||
{
|
{
|
||||||
m_inputPanel->disconnect( this );
|
m_data->inputPanel->disconnect( this );
|
||||||
|
|
||||||
if ( compositionModel )
|
if ( model )
|
||||||
compositionModel->disconnect( m_inputPanel );
|
model->disconnect( m_data->inputPanel );
|
||||||
}
|
}
|
||||||
|
|
||||||
m_inputPanel = inputPanel;
|
m_data->inputPanel = inputPanel;
|
||||||
|
|
||||||
if ( inputPanel )
|
if ( inputPanel )
|
||||||
{
|
{
|
||||||
@ -337,12 +335,12 @@ void QskInputContext::setInputPanel( QskVirtualKeyboard* inputPanel )
|
|||||||
connect( inputPanel, &QskVirtualKeyboard::localeChanged,
|
connect( inputPanel, &QskVirtualKeyboard::localeChanged,
|
||||||
this, &QPlatformInputContext::emitLocaleChanged );
|
this, &QPlatformInputContext::emitLocaleChanged );
|
||||||
|
|
||||||
if ( compositionModel )
|
if ( model )
|
||||||
{
|
{
|
||||||
inputPanel->setCandidateBarVisible(
|
inputPanel->setCandidateBarVisible(
|
||||||
compositionModel->supportsSuggestions() );
|
model->supportsSuggestions() );
|
||||||
|
|
||||||
connect( compositionModel, &QskInputCompositionModel::groupsChanged,
|
connect( model, &QskInputCompositionModel::groupsChanged,
|
||||||
inputPanel, &QskVirtualKeyboard::setPreeditGroups );
|
inputPanel, &QskVirtualKeyboard::setPreeditGroups );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,6 @@
|
|||||||
#define QSK_INPUT_CONTEXT_H
|
#define QSK_INPUT_CONTEXT_H
|
||||||
|
|
||||||
#include <qpa/qplatforminputcontext.h>
|
#include <qpa/qplatforminputcontext.h>
|
||||||
#include <QHash>
|
|
||||||
#include <QQuickItem>
|
|
||||||
#include <QPointer>
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
class QskVirtualKeyboard;
|
class QskVirtualKeyboard;
|
||||||
@ -24,36 +20,35 @@ class QskInputContext : public QPlatformInputContext
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
QskInputContext();
|
QskInputContext();
|
||||||
~QskInputContext() override;
|
virtual ~QskInputContext();
|
||||||
|
|
||||||
bool isValid() const override;
|
virtual bool isValid() const override;
|
||||||
void update( Qt::InputMethodQueries ) override;
|
|
||||||
void invokeAction( QInputMethod::Action, int ) override;
|
|
||||||
QRectF keyboardRect() const override;
|
|
||||||
bool isAnimating() const override;
|
|
||||||
void showInputPanel() override;
|
|
||||||
void hideInputPanel() override;
|
|
||||||
bool isInputPanelVisible() const override;
|
|
||||||
QLocale locale() const override;
|
|
||||||
void setFocusObject( QObject* ) override;
|
|
||||||
|
|
||||||
QskInputCompositionModel* compositionModelForLocale( const QLocale& locale ) const;
|
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 setFocusObject( QObject* ) override;
|
||||||
|
|
||||||
|
virtual QLocale locale() const override;
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void emitAnimatingChanged();
|
void emitAnimatingChanged();
|
||||||
void handleCandidatesChanged();
|
void handleCandidatesChanged();
|
||||||
void setInputPanel( QskVirtualKeyboard* );
|
void setInputPanel( QskVirtualKeyboard* );
|
||||||
void inputMethodRegistered( const QLocale& locale, QskInputCompositionModel* model );
|
void inputMethodRegistered( const QLocale&, QskInputCompositionModel* );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QskInputCompositionModel* currentInputCompositionModel() const;
|
QskInputCompositionModel* compositionModel() const;
|
||||||
void resetCandidates();
|
|
||||||
|
|
||||||
QPointer< QObject > m_focusObject;
|
class PrivateData;
|
||||||
QPointer< QQuickItem > m_inputItem;
|
std::unique_ptr< PrivateData > m_data;
|
||||||
QPointer< QskVirtualKeyboard > m_inputPanel;
|
|
||||||
QskInputCompositionModel* m_defaultInputCompositionModel;
|
|
||||||
QHash< QLocale, QskInputCompositionModel* > m_inputModels;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,16 +7,18 @@
|
|||||||
|
|
||||||
#include "QskInputContext.h"
|
#include "QskInputContext.h"
|
||||||
|
|
||||||
class QskInputContextPlugin : public QPlatformInputContextPlugin
|
class QskInputContextPlugin final : public QPlatformInputContextPlugin
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PLUGIN_METADATA( IID QPlatformInputContextFactoryInterface_iid FILE "metadata.json" )
|
Q_PLUGIN_METADATA( IID QPlatformInputContextFactoryInterface_iid FILE "metadata.json" )
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QPlatformInputContext* create( const QString& system, const QStringList& params ) override
|
virtual QPlatformInputContext* create(
|
||||||
|
const QString& system, const QStringList& ) override
|
||||||
{
|
{
|
||||||
Q_UNUSED( params );
|
if ( system.compare( QStringLiteral( "skinny" ), Qt::CaseInsensitive ) == 0 )
|
||||||
if ( system.compare( system, QLatin1String( "skinny" ), Qt::CaseInsensitive ) == 0 )
|
|
||||||
return new QskInputContext;
|
return new QskInputContext;
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -9,11 +9,12 @@
|
|||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
class QskPinyinCompositionModel::PrivateData
|
class QskPinyinCompositionModel::PrivateData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QList< QString > candidates;
|
QStringList candidates;
|
||||||
QVector< Qt::Key > groups;
|
QVector< Qt::Key > groups;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -46,12 +47,15 @@ bool QskPinyinCompositionModel::supportsSuggestions() const
|
|||||||
|
|
||||||
int QskPinyinCompositionModel::candidateCount() const
|
int QskPinyinCompositionModel::candidateCount() const
|
||||||
{
|
{
|
||||||
return qMax( 0, m_data->candidates.count() );
|
return m_data->candidates.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QskPinyinCompositionModel::candidate( int index ) const
|
QString QskPinyinCompositionModel::candidate( int index ) const
|
||||||
{
|
{
|
||||||
return m_data->candidates.at( index );
|
if ( ( index >= 0 ) && ( index < m_data->candidates.count() ) )
|
||||||
|
return m_data->candidates[ index ];
|
||||||
|
|
||||||
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector< Qt::Key > QskPinyinCompositionModel::groups() const
|
QVector< Qt::Key > QskPinyinCompositionModel::groups() const
|
||||||
@ -77,7 +81,7 @@ QString QskPinyinCompositionModel::polishPreedit( const QString& preedit )
|
|||||||
|
|
||||||
if( numSearchResults > 0 )
|
if( numSearchResults > 0 )
|
||||||
{
|
{
|
||||||
QList< QString > newCandidates;
|
QStringList newCandidates;
|
||||||
newCandidates.reserve( 1 );
|
newCandidates.reserve( 1 );
|
||||||
|
|
||||||
QVector< QChar > candidateBuffer;
|
QVector< QChar > candidateBuffer;
|
||||||
|
@ -4,21 +4,11 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "QskVirtualKeyboard.h"
|
#include "QskVirtualKeyboard.h"
|
||||||
|
#include "QskTextOptions.h"
|
||||||
|
#include "QskLinearBox.h"
|
||||||
|
|
||||||
#include "QskAspect.h"
|
|
||||||
|
|
||||||
#include <QskPushButton.h>
|
|
||||||
#include <QskTextLabel.h>
|
|
||||||
#include <QskDialog.h>
|
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
#include <QStyleHints>
|
#include <QStyleHints>
|
||||||
#include <QskLinearBox.h>
|
|
||||||
#include <QskTextOptions.h>
|
|
||||||
|
|
||||||
#include <QTimer>
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@ -133,22 +123,13 @@ static bool qskIsAutorepeat( int key )
|
|||||||
return ( key != Qt::Key_Return && key != Qt::Key_Enter
|
return ( key != Qt::Key_Return && key != Qt::Key_Enter
|
||||||
&& key != Qt::Key_Shift && key != Qt::Key_CapsLock
|
&& key != Qt::Key_Shift && key != Qt::Key_CapsLock
|
||||||
&& key != Qt::Key_Mode_switch );
|
&& key != Qt::Key_Mode_switch );
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
struct KeyCounter
|
|
||||||
{
|
|
||||||
int keyIndex;
|
|
||||||
int count;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QSK_SUBCONTROL( QskVirtualKeyboardCandidateButton, Panel )
|
QSK_SUBCONTROL( QskVirtualKeyboardCandidateButton, Panel )
|
||||||
QSK_SUBCONTROL( QskVirtualKeyboardCandidateButton, Text )
|
QSK_SUBCONTROL( QskVirtualKeyboardCandidateButton, Text )
|
||||||
|
|
||||||
QskVirtualKeyboardCandidateButton::QskVirtualKeyboardCandidateButton(QskVirtualKeyboard* inputPanel, QQuickItem* parent ) :
|
QskVirtualKeyboardCandidateButton::QskVirtualKeyboardCandidateButton(
|
||||||
|
QskVirtualKeyboard* inputPanel, QQuickItem* parent ) :
|
||||||
Inherited( parent ),
|
Inherited( parent ),
|
||||||
m_inputPanel( inputPanel ),
|
m_inputPanel( inputPanel ),
|
||||||
m_index( -1 )
|
m_index( -1 )
|
||||||
@ -195,7 +176,8 @@ QSK_SUBCONTROL( QskVirtualKeyboardButton, Panel )
|
|||||||
QSK_SUBCONTROL( QskVirtualKeyboardButton, Text )
|
QSK_SUBCONTROL( QskVirtualKeyboardButton, Text )
|
||||||
QSK_SUBCONTROL( QskVirtualKeyboardButton, TextCancelButton )
|
QSK_SUBCONTROL( QskVirtualKeyboardButton, TextCancelButton )
|
||||||
|
|
||||||
QskVirtualKeyboardButton::QskVirtualKeyboardButton( int keyIndex, QskVirtualKeyboard* inputPanel, QQuickItem* parent ) :
|
QskVirtualKeyboardButton::QskVirtualKeyboardButton(
|
||||||
|
int keyIndex, QskVirtualKeyboard* inputPanel, QQuickItem* parent ) :
|
||||||
Inherited( parent ),
|
Inherited( parent ),
|
||||||
m_keyIndex( keyIndex ),
|
m_keyIndex( keyIndex ),
|
||||||
m_inputPanel( inputPanel )
|
m_inputPanel( inputPanel )
|
||||||
@ -218,26 +200,21 @@ QskVirtualKeyboardButton::QskVirtualKeyboardButton( int keyIndex, QskVirtualKeyb
|
|||||||
|
|
||||||
updateText();
|
updateText();
|
||||||
|
|
||||||
connect( this, &QskVirtualKeyboardButton::pressed, this, [ this ]()
|
connect( this, &QskVirtualKeyboardButton::pressed, this,
|
||||||
{
|
[ this ]() { m_inputPanel->handleKey( m_keyIndex ); } );
|
||||||
m_inputPanel->handleKey( m_keyIndex );
|
|
||||||
} );
|
|
||||||
|
|
||||||
connect( m_inputPanel, &QskVirtualKeyboard::modeChanged, this, &QskVirtualKeyboardButton::updateText );
|
connect( m_inputPanel, &QskVirtualKeyboard::modeChanged,
|
||||||
|
this, &QskVirtualKeyboardButton::updateText );
|
||||||
}
|
}
|
||||||
|
|
||||||
QskAspect::Subcontrol QskVirtualKeyboardButton::effectiveSubcontrol( QskAspect::Subcontrol subControl ) const
|
QskAspect::Subcontrol QskVirtualKeyboardButton::effectiveSubcontrol(
|
||||||
|
QskAspect::Subcontrol subControl ) const
|
||||||
{
|
{
|
||||||
if( subControl == QskPushButton::Panel )
|
if( subControl == QskPushButton::Panel )
|
||||||
{
|
|
||||||
return QskVirtualKeyboardButton::Panel;
|
return QskVirtualKeyboardButton::Panel;
|
||||||
}
|
|
||||||
|
|
||||||
if( subControl == QskPushButton::Text )
|
if( subControl == QskPushButton::Text )
|
||||||
{
|
return isCancelButton() ? TextCancelButton : Text;
|
||||||
// ### we could also introduce a state to not always query the button
|
|
||||||
return isCancelButton() ? QskVirtualKeyboardButton::TextCancelButton : QskVirtualKeyboardButton::Text;
|
|
||||||
}
|
|
||||||
|
|
||||||
return subControl;
|
return subControl;
|
||||||
}
|
}
|
||||||
@ -296,7 +273,6 @@ class QskVirtualKeyboard::PrivateData
|
|||||||
QVector< Qt::Key > groups;
|
QVector< Qt::Key > groups;
|
||||||
QVector< QString > candidates;
|
QVector< QString > candidates;
|
||||||
|
|
||||||
std::unordered_map< int, KeyCounter > activeKeys;
|
|
||||||
KeyTable keyTable[ ModeCount ];
|
KeyTable keyTable[ ModeCount ];
|
||||||
|
|
||||||
QList< QskVirtualKeyboardCandidateButton* > candidateButtons;
|
QList< QskVirtualKeyboardCandidateButton* > candidateButtons;
|
||||||
@ -320,7 +296,7 @@ QskVirtualKeyboard::QskVirtualKeyboard( QQuickItem* parent ):
|
|||||||
|
|
||||||
updateLocale( locale() );
|
updateLocale( locale() );
|
||||||
|
|
||||||
QObject::connect( this, &QskControl::localeChanged,
|
connect( this, &QskControl::localeChanged,
|
||||||
this, &QskVirtualKeyboard::updateLocale );
|
this, &QskVirtualKeyboard::updateLocale );
|
||||||
|
|
||||||
setFlag( ItemIsFocusScope, true );
|
setFlag( ItemIsFocusScope, true );
|
||||||
@ -331,47 +307,43 @@ QskVirtualKeyboard::QskVirtualKeyboard( QQuickItem* parent ):
|
|||||||
|
|
||||||
setAutoLayoutChildren( true );
|
setAutoLayoutChildren( true );
|
||||||
|
|
||||||
auto& panelKeyData = keyData();
|
|
||||||
|
|
||||||
m_data->buttonsBox = new QskLinearBox( Qt::Vertical, this );
|
m_data->buttonsBox = new QskLinearBox( Qt::Vertical, this );
|
||||||
m_data->buttonsBox->setAutoAddChildren( true );
|
m_data->buttonsBox->setAutoAddChildren( true );
|
||||||
|
|
||||||
|
const auto& panelKeyData = keyData();
|
||||||
|
|
||||||
for( const auto& keyRow : panelKeyData )
|
for( const auto& keyRow : panelKeyData )
|
||||||
{
|
{
|
||||||
QskLinearBox* rowBox = new QskLinearBox( Qt::Horizontal, m_data->buttonsBox );
|
auto rowBox = new QskLinearBox( Qt::Horizontal, m_data->buttonsBox );
|
||||||
rowBox->setAutoAddChildren( true );
|
rowBox->setAutoAddChildren( true );
|
||||||
|
|
||||||
for( const auto& keyData : keyRow )
|
for( const auto& keyData : keyRow )
|
||||||
{
|
{
|
||||||
if( !keyData.key )
|
if( !keyData.key )
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
int keyIndex = m_data->keyTable[ m_data->mode ].indexOf( &keyData );
|
const int keyIndex = m_data->keyTable[ m_data->mode ].indexOf( &keyData );
|
||||||
QskVirtualKeyboardButton* button = new QskVirtualKeyboardButton( keyIndex, this, rowBox );
|
|
||||||
|
auto button = new QskVirtualKeyboardButton( keyIndex, this, rowBox );
|
||||||
rowBox->setRetainSizeWhenHidden( button, true );
|
rowBox->setRetainSizeWhenHidden( button, true );
|
||||||
|
|
||||||
m_data->keyButtons.append( button );
|
m_data->keyButtons.append( button );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
connect( this, &QskVirtualKeyboard::modeChanged, this, [ this ]() {
|
connect( this, &QskVirtualKeyboard::modeChanged,
|
||||||
updateLayout();
|
this, [ this ]() { updateLayout(); } );
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QskVirtualKeyboard::~QskVirtualKeyboard()
|
QskVirtualKeyboard::~QskVirtualKeyboard()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QskAspect::Subcontrol QskVirtualKeyboard::effectiveSubcontrol(
|
||||||
QskAspect::Subcontrol QskVirtualKeyboard::effectiveSubcontrol( QskAspect::Subcontrol subControl ) const
|
QskAspect::Subcontrol subControl ) const
|
||||||
{
|
{
|
||||||
if( subControl == QskBox::Panel )
|
if( subControl == QskBox::Panel )
|
||||||
{
|
|
||||||
return QskVirtualKeyboard::Panel;
|
return QskVirtualKeyboard::Panel;
|
||||||
}
|
|
||||||
|
|
||||||
return subControl;
|
return subControl;
|
||||||
}
|
}
|
||||||
@ -572,30 +544,31 @@ void QskVirtualKeyboard::setCandidateOffset( int candidateOffset )
|
|||||||
|
|
||||||
for( int i = 0; i < count; ++i )
|
for( int i = 0; i < count; ++i )
|
||||||
{
|
{
|
||||||
|
auto button = m_data->candidateButtons[i];
|
||||||
|
|
||||||
if( continueLeft && i == 0 )
|
if( continueLeft && i == 0 )
|
||||||
{
|
{
|
||||||
m_data->candidateButtons.at( i )->setIndexAndText( i, textForKey( Qt::Key_ApplicationLeft ) );
|
button->setIndexAndText( i, textForKey( Qt::Key_ApplicationLeft ) );
|
||||||
}
|
}
|
||||||
else if( continueRight && ( i == KeyCount - groupCount - 1 ) )
|
else if( continueRight && ( i == KeyCount - groupCount - 1 ) )
|
||||||
{
|
{
|
||||||
m_data->candidateButtons.at( i )->setIndexAndText( i, textForKey( Qt::Key_ApplicationRight ) );
|
button->setIndexAndText( i, textForKey( Qt::Key_ApplicationRight ) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int index = i + m_data->candidateOffset;
|
const int index = i + m_data->candidateOffset;
|
||||||
QString text = m_data->candidates.at( index );
|
button->setIndexAndText( index, m_data->candidates[index] );
|
||||||
m_data->candidateButtons.at( i )->setIndexAndText( index, text );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for( int i = count; i < QskVirtualKeyboardCandidateButton::maxCandidates(); ++i )
|
for( int i = count; i < QskVirtualKeyboardCandidateButton::maxCandidates(); ++i )
|
||||||
{
|
{
|
||||||
m_data->candidateButtons.at( i )->setIndexAndText( -1, QStringLiteral( "" ) );
|
m_data->candidateButtons[i]->setIndexAndText( -1, QString() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskVirtualKeyboard::registerCompositionModelForLocale( const QLocale& locale,
|
void QskVirtualKeyboard::registerCompositionModelForLocale(
|
||||||
QskInputCompositionModel* model )
|
const QLocale& locale, QskInputCompositionModel* model )
|
||||||
{
|
{
|
||||||
Q_EMIT inputMethodRegistered( locale, model );
|
Q_EMIT inputMethodRegistered( locale, model );
|
||||||
}
|
}
|
||||||
@ -604,7 +577,6 @@ void QskVirtualKeyboard::geometryChanged(
|
|||||||
const QRectF& newGeometry, const QRectF& oldGeometry )
|
const QRectF& newGeometry, const QRectF& oldGeometry )
|
||||||
{
|
{
|
||||||
Inherited::geometryChanged( newGeometry, oldGeometry );
|
Inherited::geometryChanged( newGeometry, oldGeometry );
|
||||||
|
|
||||||
Q_EMIT keyboardRectChanged();
|
Q_EMIT keyboardRectChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -637,8 +609,6 @@ void QskVirtualKeyboard::updateLayout()
|
|||||||
|
|
||||||
void QskVirtualKeyboard::createUI()
|
void QskVirtualKeyboard::createUI()
|
||||||
{
|
{
|
||||||
// deferring the UI creation until we are visible so that the contentsRect() returns the proper value
|
|
||||||
|
|
||||||
setAutoLayoutChildren( true );
|
setAutoLayoutChildren( true );
|
||||||
|
|
||||||
auto outerBox = new QskLinearBox( Qt::Vertical, this );
|
auto outerBox = new QskLinearBox( Qt::Vertical, this );
|
||||||
@ -659,17 +629,18 @@ void QskVirtualKeyboard::createUI()
|
|||||||
|
|
||||||
for( int a = 0; a < QskVirtualKeyboardCandidateButton::maxCandidates(); ++a )
|
for( int a = 0; a < QskVirtualKeyboardCandidateButton::maxCandidates(); ++a )
|
||||||
{
|
{
|
||||||
auto candidateButton = new QskVirtualKeyboardCandidateButton( this, m_data->candidateBox );
|
auto button = new QskVirtualKeyboardCandidateButton( this, m_data->candidateBox );
|
||||||
qreal height = candidateButton->sizeHint().height();
|
|
||||||
|
qreal height = button->sizeHint().height();
|
||||||
#if 1
|
#if 1
|
||||||
// should be done by margins/paddings
|
// should be done by margins/paddings
|
||||||
candidateButton->setPreferredHeight( height + 10 );
|
button->setPreferredHeight( height + 10 );
|
||||||
#endif
|
#endif
|
||||||
candidateButton->setPreferredWidth( candidateButtonWidth );
|
button->setPreferredWidth( candidateButtonWidth );
|
||||||
candidateButton->installEventFilter( this );
|
button->installEventFilter( this );
|
||||||
|
|
||||||
m_data->candidateBox->setRetainSizeWhenHidden( candidateButton, true );
|
m_data->candidateBox->setRetainSizeWhenHidden( button, true );
|
||||||
m_data->candidateButtons.append( candidateButton );
|
m_data->candidateButtons.append( button );
|
||||||
}
|
}
|
||||||
|
|
||||||
m_data->candidateBox->setVisible( m_data->candidateBoxVisible );
|
m_data->candidateBox->setVisible( m_data->candidateBoxVisible );
|
||||||
@ -678,16 +649,15 @@ void QskVirtualKeyboard::createUI()
|
|||||||
|
|
||||||
void QskVirtualKeyboard::updateUI()
|
void QskVirtualKeyboard::updateUI()
|
||||||
{
|
{
|
||||||
for( QskVirtualKeyboardButton* button : qskAsConst( m_data->keyButtons ) )
|
for( auto button : qskAsConst( m_data->keyButtons ) )
|
||||||
{
|
|
||||||
button->updateText();
|
button->updateText();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
QskVirtualKeyboard::KeyData& QskVirtualKeyboard::keyDataAt( int keyIndex ) const
|
QskVirtualKeyboard::KeyData& QskVirtualKeyboard::keyDataAt( int keyIndex ) const
|
||||||
{
|
{
|
||||||
const auto row = keyIndex / KeyCount;
|
const auto row = keyIndex / KeyCount;
|
||||||
const auto col = keyIndex % KeyCount;
|
const auto col = keyIndex % KeyCount;
|
||||||
|
|
||||||
return m_data->keyTable[ m_data->mode ].data[ row ][ col ];
|
return m_data->keyTable[ m_data->mode ].data[ row ][ col ];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,8 +125,7 @@ public:
|
|||||||
QString displayLanguageName() const;
|
QString displayLanguageName() const;
|
||||||
|
|
||||||
// takes ownership:
|
// takes ownership:
|
||||||
void registerCompositionModelForLocale( const QLocale& locale,
|
void registerCompositionModelForLocale( const QLocale&, QskInputCompositionModel* );
|
||||||
QskInputCompositionModel* model );
|
|
||||||
|
|
||||||
void handleKey( int keyIndex );
|
void handleKey( int keyIndex );
|
||||||
KeyData& keyDataAt( int ) const;
|
KeyData& keyDataAt( int ) const;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user