input panel stuff

This commit is contained in:
Uwe Rathmann 2018-04-01 12:47:44 +02:00
parent 897f6c520b
commit d947fb3999
7 changed files with 251 additions and 283 deletions

View File

@ -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 );
} }
} }

View File

@ -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

View File

@ -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;
} }
}; };

View File

@ -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;

View File

@ -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 ];
} }

View File

@ -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;