input panel stuff
This commit is contained in:
parent
897f6c520b
commit
d947fb3999
@ -146,7 +146,7 @@ void QskInputCompositionModel::composeKey( Qt::Key key )
|
||||
}
|
||||
else if( hints & Qt::ImhMultiLine )
|
||||
{
|
||||
commit( qskKeyString( key ) );
|
||||
commit( qskKeyString( key ) );
|
||||
}
|
||||
#if 0
|
||||
else
|
||||
@ -348,7 +348,7 @@ QVector< Qt::Key > QskInputCompositionModel::groups() const
|
||||
return QVector< Qt::Key >();
|
||||
}
|
||||
|
||||
void QskInputCompositionModel::setInputItem( QObject *inputItem )
|
||||
void QskInputCompositionModel::setInputItem( QObject* inputItem )
|
||||
{
|
||||
m_data->inputItem = inputItem;
|
||||
}
|
||||
|
@ -14,17 +14,30 @@
|
||||
#include <QskSetup.h>
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QHash>
|
||||
#include <QPointer>
|
||||
|
||||
QskInputContext::QskInputContext():
|
||||
Inherited(),
|
||||
m_defaultInputCompositionModel( new QskInputCompositionModel )
|
||||
class QskInputContext::PrivateData
|
||||
{
|
||||
public:
|
||||
QPointer< QQuickItem > inputItem;
|
||||
QPointer< QskVirtualKeyboard > inputPanel;
|
||||
QskInputCompositionModel* compositionModel;
|
||||
QHash< QLocale, QskInputCompositionModel* > inputModels;
|
||||
};
|
||||
|
||||
QskInputContext::QskInputContext() :
|
||||
m_data( new PrivateData() )
|
||||
{
|
||||
m_data->compositionModel = new QskInputCompositionModel();
|
||||
|
||||
connect( qskSetup, &QskSetup::inputPanelChanged,
|
||||
this, &QskInputContext::setInputPanel );
|
||||
|
||||
setInputPanel( qskSetup->inputPanel() );
|
||||
|
||||
QskPinyinCompositionModel* pinyinModel = new QskPinyinCompositionModel;
|
||||
// For input methods outside skinny, call QskInputPanel::registerCompositionModelForLocale()
|
||||
// see also: QskVirtualKeyboard::registerCompositionModelForLocale()
|
||||
inputMethodRegistered( QLocale::Chinese, pinyinModel );
|
||||
|
||||
// We could connect candidatesChanged() here, but we don't emit
|
||||
@ -33,13 +46,10 @@ QskInputContext::QskInputContext():
|
||||
|
||||
QskInputContext::~QskInputContext()
|
||||
{
|
||||
if ( m_inputPanel )
|
||||
delete m_inputPanel;
|
||||
if ( m_data->inputPanel )
|
||||
delete m_data->inputPanel;
|
||||
|
||||
for( int a = 0; a < m_inputModels.values().count(); a++ )
|
||||
{
|
||||
delete m_inputModels.values()[a];
|
||||
}
|
||||
qDeleteAll( m_data->inputModels );
|
||||
}
|
||||
|
||||
bool QskInputContext::isValid() const
|
||||
@ -49,11 +59,11 @@ bool QskInputContext::isValid() const
|
||||
|
||||
void QskInputContext::update( Qt::InputMethodQueries queries )
|
||||
{
|
||||
if ( !m_inputItem )
|
||||
if ( !m_data->inputItem )
|
||||
return;
|
||||
|
||||
QInputMethodQueryEvent queryEvent( queries );
|
||||
if ( !QCoreApplication::sendEvent( m_inputItem, &queryEvent ) )
|
||||
if ( !QCoreApplication::sendEvent( m_data->inputItem, &queryEvent ) )
|
||||
return;
|
||||
|
||||
// Qt::ImCursorRectangle
|
||||
@ -98,26 +108,24 @@ void QskInputContext::update( Qt::InputMethodQueries queries )
|
||||
{
|
||||
const auto locale = queryEvent.value( Qt::ImPreferredLanguage ).toLocale();
|
||||
|
||||
auto oldModel = currentInputCompositionModel();
|
||||
auto oldModel = compositionModel();
|
||||
|
||||
if( m_inputPanel )
|
||||
m_inputPanel->setLocale( locale );
|
||||
if( m_data->inputPanel )
|
||||
m_data->inputPanel->setLocale( locale );
|
||||
|
||||
auto newModel = currentInputCompositionModel();
|
||||
auto newModel = compositionModel();
|
||||
|
||||
bool modelChanged = ( oldModel != newModel );
|
||||
|
||||
if( modelChanged )
|
||||
if( oldModel != newModel )
|
||||
{
|
||||
if( m_inputPanel )
|
||||
if( m_data->inputPanel )
|
||||
{
|
||||
m_inputPanel->setCandidateBarVisible( newModel->supportsSuggestions() );
|
||||
m_inputPanel->disconnect( oldModel );
|
||||
QObject::connect(
|
||||
newModel, &QskInputCompositionModel::groupsChanged,
|
||||
m_inputPanel.data(), &QskVirtualKeyboard::setPreeditGroups );
|
||||
QObject::connect(
|
||||
newModel, &QskInputCompositionModel::candidatesChanged,
|
||||
m_data->inputPanel->setCandidateBarVisible( newModel->supportsSuggestions() );
|
||||
m_data->inputPanel->disconnect( oldModel );
|
||||
|
||||
connect( newModel, &QskInputCompositionModel::groupsChanged,
|
||||
m_data->inputPanel.data(), &QskVirtualKeyboard::setPreeditGroups );
|
||||
|
||||
connect( newModel, &QskInputCompositionModel::candidatesChanged,
|
||||
this, &QskInputContext::handleCandidatesChanged );
|
||||
}
|
||||
}
|
||||
@ -131,10 +139,10 @@ void QskInputContext::update( Qt::InputMethodQueries queries )
|
||||
|
||||
QRectF QskInputContext::keyboardRect() const
|
||||
{
|
||||
if ( m_inputPanel
|
||||
if ( m_data->inputPanel
|
||||
&& QskDialog::instance()->policy() != QskDialog::TopLevelWindow )
|
||||
{
|
||||
return m_inputPanel->geometry();
|
||||
return m_data->inputPanel->geometry();
|
||||
}
|
||||
|
||||
return Inherited::keyboardRect();
|
||||
@ -147,16 +155,16 @@ bool QskInputContext::isAnimating() const
|
||||
|
||||
void QskInputContext::showInputPanel()
|
||||
{
|
||||
if ( !m_inputPanel )
|
||||
if ( !m_data->inputPanel )
|
||||
{
|
||||
setInputPanel( new QskVirtualKeyboard );
|
||||
setInputPanel( new QskVirtualKeyboard() );
|
||||
|
||||
if ( QskDialog::instance()->policy() == QskDialog::TopLevelWindow )
|
||||
{
|
||||
auto window = new QskWindow;
|
||||
window->setFlags( Qt::Tool | Qt::WindowDoesNotAcceptFocus );
|
||||
window->resize( 800, 240 ); // ### what size?
|
||||
m_inputPanel->setParentItem( window->contentItem() );
|
||||
m_data->inputPanel->setParentItem( window->contentItem() );
|
||||
connect( window, &QskWindow::visibleChanged,
|
||||
this, &QskInputContext::emitInputPanelVisibleChanged );
|
||||
}
|
||||
@ -165,62 +173,62 @@ void QskInputContext::showInputPanel()
|
||||
auto window = qobject_cast< QQuickWindow* >( QGuiApplication::focusWindow() );
|
||||
if ( window )
|
||||
{
|
||||
m_inputPanel->setParentItem( window->contentItem() );
|
||||
m_inputPanel->setSize( window->size() );
|
||||
m_data->inputPanel->setParentItem( window->contentItem() );
|
||||
m_data->inputPanel->setSize( window->size() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto window = m_inputPanel->window();
|
||||
auto window = m_data->inputPanel->window();
|
||||
if ( window && window != QGuiApplication::focusWindow() )
|
||||
window->show();
|
||||
else
|
||||
m_inputPanel->setVisible( true );
|
||||
m_data->inputPanel->setVisible( true );
|
||||
}
|
||||
|
||||
void QskInputContext::hideInputPanel()
|
||||
{
|
||||
if ( !m_inputPanel )
|
||||
if ( !m_data->inputPanel )
|
||||
return;
|
||||
|
||||
auto window = m_inputPanel->window();
|
||||
auto window = m_data->inputPanel->window();
|
||||
if ( window && window != QGuiApplication::focusWindow() )
|
||||
window->hide();
|
||||
else
|
||||
m_inputPanel->setVisible( false );
|
||||
m_data->inputPanel->setVisible( false );
|
||||
}
|
||||
|
||||
bool QskInputContext::isInputPanelVisible() const
|
||||
{
|
||||
return m_inputPanel && m_inputPanel->isVisible()
|
||||
&& m_inputPanel->window() && m_inputPanel->window()->isVisible();
|
||||
auto panel = m_data->inputPanel;
|
||||
return panel && panel->isVisible()
|
||||
&& panel->window() && panel->window()->isVisible();
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
m_focusObject = focusObject;
|
||||
if ( !m_focusObject )
|
||||
if ( focusObject == nullptr )
|
||||
{
|
||||
m_inputItem = nullptr;
|
||||
currentInputCompositionModel()->setInputItem( nullptr );
|
||||
m_data->inputItem = nullptr;
|
||||
compositionModel()->setInputItem( nullptr );
|
||||
return;
|
||||
}
|
||||
|
||||
bool inputItemChanged = false;
|
||||
|
||||
auto focusQuickItem = qobject_cast< QQuickItem* >( focusObject );
|
||||
if( focusQuickItem )
|
||||
auto focusItem = qobject_cast< QQuickItem* >( focusObject );
|
||||
if( focusItem )
|
||||
{
|
||||
// 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;
|
||||
currentInputCompositionModel()->setInputItem( m_inputItem ); // ### use a signal/slot connection
|
||||
m_data->inputItem = focusItem;
|
||||
compositionModel()->setInputItem( focusItem );
|
||||
inputItemChanged = true;
|
||||
}
|
||||
}
|
||||
@ -228,7 +236,7 @@ void QskInputContext::setFocusObject( QObject* focusObject )
|
||||
if( inputItemChanged )
|
||||
{
|
||||
QInputMethodQueryEvent queryEvent( Qt::ImEnabled );
|
||||
if ( !QCoreApplication::sendEvent( m_inputItem, &queryEvent ) )
|
||||
if ( !QCoreApplication::sendEvent( m_data->inputItem, &queryEvent ) )
|
||||
return;
|
||||
|
||||
if ( !queryEvent.value( Qt::ImEnabled ).toBool() )
|
||||
@ -241,54 +249,44 @@ void QskInputContext::setFocusObject( QObject* focusObject )
|
||||
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();
|
||||
}
|
||||
|
||||
m_inputModels.insert( locale, model );
|
||||
m_data->inputModels.insert( locale, model );
|
||||
}
|
||||
|
||||
QskInputCompositionModel* QskInputContext::compositionModelForLocale( const QLocale& locale ) const
|
||||
QskInputCompositionModel* QskInputContext::compositionModel() const
|
||||
{
|
||||
return m_inputModels.value( locale, m_defaultInputCompositionModel );
|
||||
}
|
||||
|
||||
QskInputCompositionModel* QskInputContext::currentInputCompositionModel() const
|
||||
{
|
||||
return m_inputModels.value( locale(), m_defaultInputCompositionModel );
|
||||
}
|
||||
|
||||
void QskInputContext::resetCandidates()
|
||||
{
|
||||
m_inputPanel->setPreeditCandidates( {} );
|
||||
return m_data->inputModels.value( locale(), m_data->compositionModel );
|
||||
}
|
||||
|
||||
void QskInputContext::invokeAction( QInputMethod::Action action, int cursorPosition )
|
||||
{
|
||||
Q_UNUSED( cursorPosition );
|
||||
|
||||
if ( !m_inputPanel )
|
||||
return;
|
||||
auto model = compositionModel();
|
||||
|
||||
switch ( static_cast< QskVirtualKeyboard::Action >( action ) )
|
||||
{
|
||||
case QskVirtualKeyboard::Compose:
|
||||
currentInputCompositionModel()->composeKey( static_cast< Qt::Key >( cursorPosition ) );
|
||||
{
|
||||
model->composeKey( static_cast< Qt::Key >( cursorPosition ) );
|
||||
break;
|
||||
|
||||
}
|
||||
case QskVirtualKeyboard::SelectGroup:
|
||||
currentInputCompositionModel()->setGroupIndex( cursorPosition );
|
||||
{
|
||||
model->setGroupIndex( cursorPosition );
|
||||
break;
|
||||
|
||||
}
|
||||
case QskVirtualKeyboard::SelectCandidate:
|
||||
currentInputCompositionModel()->commitCandidate( cursorPosition );
|
||||
resetCandidates();
|
||||
{
|
||||
model->commitCandidate( cursorPosition );
|
||||
if ( m_data->inputPanel )
|
||||
m_data->inputPanel->setPreeditCandidates( QVector< QString >() );
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -299,32 +297,32 @@ void QskInputContext::emitAnimatingChanged()
|
||||
|
||||
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 )
|
||||
{
|
||||
candidates[i] = currentInputCompositionModel()->candidate( i );
|
||||
}
|
||||
candidates[i] = model->candidate( i );
|
||||
|
||||
m_inputPanel->setPreeditCandidates( candidates );
|
||||
m_data->inputPanel->setPreeditCandidates( candidates );
|
||||
}
|
||||
|
||||
void QskInputContext::setInputPanel( QskVirtualKeyboard* inputPanel )
|
||||
{
|
||||
if ( m_inputPanel == inputPanel )
|
||||
if ( m_data->inputPanel == inputPanel )
|
||||
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 )
|
||||
compositionModel->disconnect( m_inputPanel );
|
||||
if ( model )
|
||||
model->disconnect( m_data->inputPanel );
|
||||
}
|
||||
|
||||
m_inputPanel = inputPanel;
|
||||
m_data->inputPanel = inputPanel;
|
||||
|
||||
if ( inputPanel )
|
||||
{
|
||||
@ -337,12 +335,12 @@ void QskInputContext::setInputPanel( QskVirtualKeyboard* inputPanel )
|
||||
connect( inputPanel, &QskVirtualKeyboard::localeChanged,
|
||||
this, &QPlatformInputContext::emitLocaleChanged );
|
||||
|
||||
if ( compositionModel )
|
||||
if ( model )
|
||||
{
|
||||
inputPanel->setCandidateBarVisible(
|
||||
compositionModel->supportsSuggestions() );
|
||||
model->supportsSuggestions() );
|
||||
|
||||
connect( compositionModel, &QskInputCompositionModel::groupsChanged,
|
||||
connect( model, &QskInputCompositionModel::groupsChanged,
|
||||
inputPanel, &QskVirtualKeyboard::setPreeditGroups );
|
||||
}
|
||||
}
|
||||
|
@ -7,10 +7,6 @@
|
||||
#define QSK_INPUT_CONTEXT_H
|
||||
|
||||
#include <qpa/qplatforminputcontext.h>
|
||||
#include <QHash>
|
||||
#include <QQuickItem>
|
||||
#include <QPointer>
|
||||
|
||||
#include <memory>
|
||||
|
||||
class QskVirtualKeyboard;
|
||||
@ -24,36 +20,35 @@ class QskInputContext : public QPlatformInputContext
|
||||
|
||||
public:
|
||||
QskInputContext();
|
||||
~QskInputContext() override;
|
||||
virtual ~QskInputContext();
|
||||
|
||||
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;
|
||||
virtual bool isValid() const 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:
|
||||
void emitAnimatingChanged();
|
||||
void handleCandidatesChanged();
|
||||
void setInputPanel( QskVirtualKeyboard* );
|
||||
void inputMethodRegistered( const QLocale& locale, QskInputCompositionModel* model );
|
||||
void inputMethodRegistered( const QLocale&, QskInputCompositionModel* );
|
||||
|
||||
private:
|
||||
QskInputCompositionModel* currentInputCompositionModel() const;
|
||||
void resetCandidates();
|
||||
QskInputCompositionModel* compositionModel() const;
|
||||
|
||||
QPointer< QObject > m_focusObject;
|
||||
QPointer< QQuickItem > m_inputItem;
|
||||
QPointer< QskVirtualKeyboard > m_inputPanel;
|
||||
QskInputCompositionModel* m_defaultInputCompositionModel;
|
||||
QHash< QLocale, QskInputCompositionModel* > m_inputModels;
|
||||
class PrivateData;
|
||||
std::unique_ptr< PrivateData > m_data;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -7,16 +7,18 @@
|
||||
|
||||
#include "QskInputContext.h"
|
||||
|
||||
class QskInputContextPlugin : public QPlatformInputContextPlugin
|
||||
class QskInputContextPlugin final : public QPlatformInputContextPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA( IID QPlatformInputContextFactoryInterface_iid FILE "metadata.json" )
|
||||
|
||||
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( system, QLatin1String( "skinny" ), Qt::CaseInsensitive ) == 0 )
|
||||
if ( system.compare( QStringLiteral( "skinny" ), Qt::CaseInsensitive ) == 0 )
|
||||
return new QskInputContext;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
@ -9,11 +9,12 @@
|
||||
|
||||
#include <QDebug>
|
||||
#include <QVector>
|
||||
#include <QStringList>
|
||||
|
||||
class QskPinyinCompositionModel::PrivateData
|
||||
{
|
||||
public:
|
||||
QList< QString > candidates;
|
||||
QStringList candidates;
|
||||
QVector< Qt::Key > groups;
|
||||
};
|
||||
|
||||
@ -46,12 +47,15 @@ bool QskPinyinCompositionModel::supportsSuggestions() const
|
||||
|
||||
int QskPinyinCompositionModel::candidateCount() const
|
||||
{
|
||||
return qMax( 0, m_data->candidates.count() );
|
||||
return m_data->candidates.count();
|
||||
}
|
||||
|
||||
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
|
||||
@ -77,7 +81,7 @@ QString QskPinyinCompositionModel::polishPreedit( const QString& preedit )
|
||||
|
||||
if( numSearchResults > 0 )
|
||||
{
|
||||
QList< QString > newCandidates;
|
||||
QStringList newCandidates;
|
||||
newCandidates.reserve( 1 );
|
||||
|
||||
QVector< QChar > candidateBuffer;
|
||||
|
@ -4,21 +4,11 @@
|
||||
*****************************************************************************/
|
||||
|
||||
#include "QskVirtualKeyboard.h"
|
||||
#include "QskTextOptions.h"
|
||||
#include "QskLinearBox.h"
|
||||
|
||||
#include "QskAspect.h"
|
||||
|
||||
#include <QskPushButton.h>
|
||||
#include <QskTextLabel.h>
|
||||
#include <QskDialog.h>
|
||||
#include <QGuiApplication>
|
||||
#include <QStyleHints>
|
||||
#include <QskLinearBox.h>
|
||||
#include <QskTextOptions.h>
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
#include <cmath>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -131,24 +121,15 @@ static qreal qskRowStretch( const QskVirtualKeyboard::KeyRow& keyRow )
|
||||
static bool qskIsAutorepeat( int key )
|
||||
{
|
||||
return ( key != Qt::Key_Return && key != Qt::Key_Enter
|
||||
&& key != Qt::Key_Shift && key!= Qt::Key_CapsLock
|
||||
&& key != Qt::Key_Mode_switch );
|
||||
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct KeyCounter
|
||||
{
|
||||
int keyIndex;
|
||||
int count;
|
||||
};
|
||||
&& key != Qt::Key_Shift && key != Qt::Key_CapsLock
|
||||
&& key != Qt::Key_Mode_switch );
|
||||
}
|
||||
|
||||
QSK_SUBCONTROL( QskVirtualKeyboardCandidateButton, Panel )
|
||||
QSK_SUBCONTROL( QskVirtualKeyboardCandidateButton, Text )
|
||||
|
||||
QskVirtualKeyboardCandidateButton::QskVirtualKeyboardCandidateButton(QskVirtualKeyboard* inputPanel, QQuickItem* parent ) :
|
||||
QskVirtualKeyboardCandidateButton::QskVirtualKeyboardCandidateButton(
|
||||
QskVirtualKeyboard* inputPanel, QQuickItem* parent ) :
|
||||
Inherited( parent ),
|
||||
m_inputPanel( inputPanel ),
|
||||
m_index( -1 )
|
||||
@ -195,7 +176,8 @@ QSK_SUBCONTROL( QskVirtualKeyboardButton, Panel )
|
||||
QSK_SUBCONTROL( QskVirtualKeyboardButton, Text )
|
||||
QSK_SUBCONTROL( QskVirtualKeyboardButton, TextCancelButton )
|
||||
|
||||
QskVirtualKeyboardButton::QskVirtualKeyboardButton( int keyIndex, QskVirtualKeyboard* inputPanel, QQuickItem* parent ) :
|
||||
QskVirtualKeyboardButton::QskVirtualKeyboardButton(
|
||||
int keyIndex, QskVirtualKeyboard* inputPanel, QQuickItem* parent ) :
|
||||
Inherited( parent ),
|
||||
m_keyIndex( keyIndex ),
|
||||
m_inputPanel( inputPanel )
|
||||
@ -218,26 +200,21 @@ QskVirtualKeyboardButton::QskVirtualKeyboardButton( int keyIndex, QskVirtualKeyb
|
||||
|
||||
updateText();
|
||||
|
||||
connect( this, &QskVirtualKeyboardButton::pressed, this, [ this ]()
|
||||
{
|
||||
m_inputPanel->handleKey( m_keyIndex );
|
||||
} );
|
||||
connect( this, &QskVirtualKeyboardButton::pressed, this,
|
||||
[ this ]() { 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 )
|
||||
{
|
||||
return QskVirtualKeyboardButton::Panel;
|
||||
}
|
||||
|
||||
if( subControl == QskPushButton::Text )
|
||||
{
|
||||
// ### we could also introduce a state to not always query the button
|
||||
return isCancelButton() ? QskVirtualKeyboardButton::TextCancelButton : QskVirtualKeyboardButton::Text;
|
||||
}
|
||||
return isCancelButton() ? TextCancelButton : Text;
|
||||
|
||||
return subControl;
|
||||
}
|
||||
@ -271,40 +248,39 @@ bool QskVirtualKeyboardButton::isCancelButton() const
|
||||
|
||||
class QskVirtualKeyboard::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData():
|
||||
currentLayout( nullptr ),
|
||||
mode( QskVirtualKeyboard::LowercaseMode ),
|
||||
selectedGroup( -1 ),
|
||||
candidateOffset( 0 ),
|
||||
candidateBox( nullptr ),
|
||||
buttonsBox( nullptr ),
|
||||
isUIInitialized( false ),
|
||||
candidateBoxVisible( false )
|
||||
{
|
||||
}
|
||||
public:
|
||||
PrivateData():
|
||||
currentLayout( nullptr ),
|
||||
mode( QskVirtualKeyboard::LowercaseMode ),
|
||||
selectedGroup( -1 ),
|
||||
candidateOffset( 0 ),
|
||||
candidateBox( nullptr ),
|
||||
buttonsBox( nullptr ),
|
||||
isUIInitialized( false ),
|
||||
candidateBoxVisible( false )
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
const QskVirtualKeyboardLayouts::Layout* currentLayout;
|
||||
QskVirtualKeyboard::Mode mode;
|
||||
public:
|
||||
const QskVirtualKeyboardLayouts::Layout* currentLayout;
|
||||
QskVirtualKeyboard::Mode mode;
|
||||
|
||||
qint16 selectedGroup;
|
||||
qint32 candidateOffset;
|
||||
qint16 selectedGroup;
|
||||
qint32 candidateOffset;
|
||||
|
||||
QLocale locale;
|
||||
QLocale locale;
|
||||
|
||||
QVector< Qt::Key > groups;
|
||||
QVector< QString > candidates;
|
||||
QVector< Qt::Key > groups;
|
||||
QVector< QString > candidates;
|
||||
|
||||
std::unordered_map< int, KeyCounter > activeKeys;
|
||||
KeyTable keyTable[ ModeCount ];
|
||||
KeyTable keyTable[ ModeCount ];
|
||||
|
||||
QList< QskVirtualKeyboardCandidateButton* > candidateButtons;
|
||||
QskLinearBox* candidateBox;
|
||||
QskLinearBox* buttonsBox;
|
||||
QList< QskVirtualKeyboardButton* > keyButtons;
|
||||
bool isUIInitialized;
|
||||
bool candidateBoxVisible;
|
||||
QList< QskVirtualKeyboardCandidateButton* > candidateButtons;
|
||||
QskLinearBox* candidateBox;
|
||||
QskLinearBox* buttonsBox;
|
||||
QList< QskVirtualKeyboardButton* > keyButtons;
|
||||
bool isUIInitialized;
|
||||
bool candidateBoxVisible;
|
||||
};
|
||||
|
||||
QskVirtualKeyboard::QskVirtualKeyboard( QQuickItem* parent ):
|
||||
@ -320,8 +296,8 @@ QskVirtualKeyboard::QskVirtualKeyboard( QQuickItem* parent ):
|
||||
|
||||
updateLocale( locale() );
|
||||
|
||||
QObject::connect( this, &QskControl::localeChanged,
|
||||
this, &QskVirtualKeyboard::updateLocale );
|
||||
connect( this, &QskControl::localeChanged,
|
||||
this, &QskVirtualKeyboard::updateLocale );
|
||||
|
||||
setFlag( ItemIsFocusScope, true );
|
||||
|
||||
@ -331,47 +307,43 @@ QskVirtualKeyboard::QskVirtualKeyboard( QQuickItem* parent ):
|
||||
|
||||
setAutoLayoutChildren( true );
|
||||
|
||||
auto& panelKeyData = keyData();
|
||||
|
||||
m_data->buttonsBox = new QskLinearBox( Qt::Vertical, this );
|
||||
m_data->buttonsBox->setAutoAddChildren( true );
|
||||
|
||||
const auto& panelKeyData = keyData();
|
||||
|
||||
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 );
|
||||
|
||||
for( const auto& keyData : keyRow )
|
||||
{
|
||||
if( !keyData.key )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int keyIndex = m_data->keyTable[ m_data->mode ].indexOf( &keyData );
|
||||
QskVirtualKeyboardButton* button = new QskVirtualKeyboardButton( keyIndex, this, rowBox );
|
||||
const int keyIndex = m_data->keyTable[ m_data->mode ].indexOf( &keyData );
|
||||
|
||||
auto button = new QskVirtualKeyboardButton( keyIndex, this, rowBox );
|
||||
rowBox->setRetainSizeWhenHidden( button, true );
|
||||
|
||||
m_data->keyButtons.append( button );
|
||||
}
|
||||
}
|
||||
|
||||
connect( this, &QskVirtualKeyboard::modeChanged, this, [ this ]() {
|
||||
updateLayout();
|
||||
});
|
||||
connect( this, &QskVirtualKeyboard::modeChanged,
|
||||
this, [ this ]() { updateLayout(); } );
|
||||
}
|
||||
|
||||
QskVirtualKeyboard::~QskVirtualKeyboard()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
QskAspect::Subcontrol QskVirtualKeyboard::effectiveSubcontrol( QskAspect::Subcontrol subControl ) const
|
||||
QskAspect::Subcontrol QskVirtualKeyboard::effectiveSubcontrol(
|
||||
QskAspect::Subcontrol subControl ) const
|
||||
{
|
||||
if( subControl == QskBox::Panel )
|
||||
{
|
||||
return QskVirtualKeyboard::Panel;
|
||||
}
|
||||
|
||||
return subControl;
|
||||
}
|
||||
@ -459,22 +431,22 @@ QString QskVirtualKeyboard::displayLanguageName() const
|
||||
return QStringLiteral( "Eλληνικά" );
|
||||
|
||||
case QLocale::English:
|
||||
{
|
||||
switch( locale.country() )
|
||||
{
|
||||
switch( locale.country() )
|
||||
{
|
||||
case QLocale::Canada:
|
||||
case QLocale::UnitedStates:
|
||||
case QLocale::UnitedStatesMinorOutlyingIslands:
|
||||
case QLocale::UnitedStatesVirginIslands:
|
||||
return QStringLiteral( "English (US)" );
|
||||
case QLocale::Canada:
|
||||
case QLocale::UnitedStates:
|
||||
case QLocale::UnitedStatesMinorOutlyingIslands:
|
||||
case QLocale::UnitedStatesVirginIslands:
|
||||
return QStringLiteral( "English (US)" );
|
||||
|
||||
default:
|
||||
return QStringLiteral( "English (UK)" );
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
return QStringLiteral( "English (UK)" );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case QLocale::Spanish:
|
||||
return QStringLiteral( "Español" );
|
||||
|
||||
@ -572,30 +544,31 @@ void QskVirtualKeyboard::setCandidateOffset( int candidateOffset )
|
||||
|
||||
for( int i = 0; i < count; ++i )
|
||||
{
|
||||
auto button = m_data->candidateButtons[i];
|
||||
|
||||
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 ) )
|
||||
{
|
||||
m_data->candidateButtons.at( i )->setIndexAndText( i, textForKey( Qt::Key_ApplicationRight ) );
|
||||
button->setIndexAndText( i, textForKey( Qt::Key_ApplicationRight ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
int index = i + m_data->candidateOffset;
|
||||
QString text = m_data->candidates.at( index );
|
||||
m_data->candidateButtons.at( i )->setIndexAndText( index, text );
|
||||
const int index = i + m_data->candidateOffset;
|
||||
button->setIndexAndText( index, m_data->candidates[index] );
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
QskInputCompositionModel* model )
|
||||
void QskVirtualKeyboard::registerCompositionModelForLocale(
|
||||
const QLocale& locale, QskInputCompositionModel* model )
|
||||
{
|
||||
Q_EMIT inputMethodRegistered( locale, model );
|
||||
}
|
||||
@ -604,7 +577,6 @@ void QskVirtualKeyboard::geometryChanged(
|
||||
const QRectF& newGeometry, const QRectF& oldGeometry )
|
||||
{
|
||||
Inherited::geometryChanged( newGeometry, oldGeometry );
|
||||
|
||||
Q_EMIT keyboardRectChanged();
|
||||
}
|
||||
|
||||
@ -637,8 +609,6 @@ void QskVirtualKeyboard::updateLayout()
|
||||
|
||||
void QskVirtualKeyboard::createUI()
|
||||
{
|
||||
// deferring the UI creation until we are visible so that the contentsRect() returns the proper value
|
||||
|
||||
setAutoLayoutChildren( true );
|
||||
|
||||
auto outerBox = new QskLinearBox( Qt::Vertical, this );
|
||||
@ -655,21 +625,22 @@ void QskVirtualKeyboard::createUI()
|
||||
// ### Can this be done with the layout engine or so?
|
||||
QRectF rect = layoutRect();
|
||||
auto candidateButtonWidth = rect.width() / QskVirtualKeyboardCandidateButton::maxCandidates()
|
||||
- m_data->candidateBox->spacing() * QskVirtualKeyboardCandidateButton::maxCandidates();
|
||||
- m_data->candidateBox->spacing() * QskVirtualKeyboardCandidateButton::maxCandidates();
|
||||
|
||||
for( int a = 0; a < QskVirtualKeyboardCandidateButton::maxCandidates(); ++a )
|
||||
{
|
||||
auto candidateButton = new QskVirtualKeyboardCandidateButton( this, m_data->candidateBox );
|
||||
qreal height = candidateButton->sizeHint().height();
|
||||
#if 1
|
||||
// should be done by margins/paddings
|
||||
candidateButton->setPreferredHeight( height + 10 );
|
||||
#endif
|
||||
candidateButton->setPreferredWidth( candidateButtonWidth );
|
||||
candidateButton->installEventFilter( this );
|
||||
auto button = new QskVirtualKeyboardCandidateButton( this, m_data->candidateBox );
|
||||
|
||||
m_data->candidateBox->setRetainSizeWhenHidden( candidateButton, true );
|
||||
m_data->candidateButtons.append( candidateButton );
|
||||
qreal height = button->sizeHint().height();
|
||||
#if 1
|
||||
// should be done by margins/paddings
|
||||
button->setPreferredHeight( height + 10 );
|
||||
#endif
|
||||
button->setPreferredWidth( candidateButtonWidth );
|
||||
button->installEventFilter( this );
|
||||
|
||||
m_data->candidateBox->setRetainSizeWhenHidden( button, true );
|
||||
m_data->candidateButtons.append( button );
|
||||
}
|
||||
|
||||
m_data->candidateBox->setVisible( m_data->candidateBoxVisible );
|
||||
@ -678,16 +649,15 @@ void QskVirtualKeyboard::createUI()
|
||||
|
||||
void QskVirtualKeyboard::updateUI()
|
||||
{
|
||||
for( QskVirtualKeyboardButton* button : qskAsConst( m_data->keyButtons ) )
|
||||
{
|
||||
for( auto button : qskAsConst( m_data->keyButtons ) )
|
||||
button->updateText();
|
||||
}
|
||||
}
|
||||
|
||||
QskVirtualKeyboard::KeyData& QskVirtualKeyboard::keyDataAt( int keyIndex ) const
|
||||
{
|
||||
const auto row = keyIndex / KeyCount;
|
||||
const auto col = keyIndex % KeyCount;
|
||||
|
||||
return m_data->keyTable[ m_data->mode ].data[ row ][ col ];
|
||||
}
|
||||
|
||||
@ -711,8 +681,8 @@ void QskVirtualKeyboard::handleKey( int keyIndex )
|
||||
|
||||
case Qt::Key_Mode_switch: // Cycle through modes, but skip caps
|
||||
setMode( static_cast< QskVirtualKeyboard::Mode >(
|
||||
m_data->mode ? ( ( m_data->mode + 1 ) % QskVirtualKeyboard::ModeCount )
|
||||
: SpecialCharacterMode ) );
|
||||
m_data->mode ? ( ( m_data->mode + 1 ) % QskVirtualKeyboard::ModeCount )
|
||||
: SpecialCharacterMode ) );
|
||||
return;
|
||||
|
||||
// This is (one of) the cancel symbol, not Qt::Key_Cancel:
|
||||
@ -822,24 +792,24 @@ void QskVirtualKeyboard::updateLocale( const QLocale& locale )
|
||||
break;
|
||||
|
||||
case QLocale::English:
|
||||
{
|
||||
switch( locale.country() )
|
||||
{
|
||||
switch( locale.country() )
|
||||
{
|
||||
case QLocale::Canada:
|
||||
case QLocale::UnitedStates:
|
||||
case QLocale::UnitedStatesMinorOutlyingIslands:
|
||||
case QLocale::UnitedStatesVirginIslands:
|
||||
m_data->currentLayout = &qskKeyboardLayouts.en_US;
|
||||
break;
|
||||
case QLocale::Canada:
|
||||
case QLocale::UnitedStates:
|
||||
case QLocale::UnitedStatesMinorOutlyingIslands:
|
||||
case QLocale::UnitedStatesVirginIslands:
|
||||
m_data->currentLayout = &qskKeyboardLayouts.en_US;
|
||||
break;
|
||||
|
||||
default:
|
||||
m_data->currentLayout = &qskKeyboardLayouts.en_GB;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
m_data->currentLayout = &qskKeyboardLayouts.en_GB;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case QLocale::Spanish:
|
||||
m_data->currentLayout = &qskKeyboardLayouts.es;
|
||||
break;
|
||||
|
@ -39,27 +39,27 @@ private:
|
||||
|
||||
class QSK_EXPORT QskVirtualKeyboardButton : public QskPushButton
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
using Inherited = QskPushButton;
|
||||
using Inherited = QskPushButton;
|
||||
|
||||
public:
|
||||
QSK_SUBCONTROLS( Panel, Text, TextCancelButton )
|
||||
public:
|
||||
QSK_SUBCONTROLS( Panel, Text, TextCancelButton )
|
||||
|
||||
QskVirtualKeyboardButton( int keyIndex, QskVirtualKeyboard* inputPanel, QQuickItem* parent = nullptr );
|
||||
QskVirtualKeyboardButton( int keyIndex, QskVirtualKeyboard* inputPanel, QQuickItem* parent = nullptr );
|
||||
|
||||
virtual QskAspect::Subcontrol effectiveSubcontrol( QskAspect::Subcontrol subControl ) const override;
|
||||
virtual QskAspect::Subcontrol effectiveSubcontrol( QskAspect::Subcontrol subControl ) const override;
|
||||
|
||||
int keyIndex() const;
|
||||
int keyIndex() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void updateText();
|
||||
public Q_SLOTS:
|
||||
void updateText();
|
||||
|
||||
private:
|
||||
bool isCancelButton() const;
|
||||
private:
|
||||
bool isCancelButton() const;
|
||||
|
||||
const int m_keyIndex;
|
||||
QskVirtualKeyboard* m_inputPanel;
|
||||
const int m_keyIndex;
|
||||
QskVirtualKeyboard* m_inputPanel;
|
||||
};
|
||||
|
||||
class QSK_EXPORT QskVirtualKeyboard : public QskBox
|
||||
@ -67,7 +67,7 @@ class QSK_EXPORT QskVirtualKeyboard : public QskBox
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY( QString displayLanguageName READ displayLanguageName
|
||||
NOTIFY displayLanguageNameChanged )
|
||||
NOTIFY displayLanguageNameChanged )
|
||||
|
||||
using Inherited = QskBox;
|
||||
|
||||
@ -125,19 +125,18 @@ public:
|
||||
QString displayLanguageName() const;
|
||||
|
||||
// takes ownership:
|
||||
void registerCompositionModelForLocale( const QLocale& locale,
|
||||
QskInputCompositionModel* model );
|
||||
void registerCompositionModelForLocale( const QLocale&, QskInputCompositionModel* );
|
||||
|
||||
void handleKey( int keyIndex );
|
||||
KeyData& keyDataAt( int ) const;
|
||||
QString currentTextForKeyIndex( int keyIndex ) const;
|
||||
|
||||
void handleCandidateKey( int index, const QString &text );
|
||||
void handleCandidateKey( int index, const QString& text );
|
||||
void setCandidateBarVisible( bool visible );
|
||||
|
||||
public Q_SLOTS:
|
||||
void setPreeditGroups( const QVector< Qt::Key >& );
|
||||
void setPreeditCandidates(const QVector< QString > & );
|
||||
void setPreeditCandidates(const QVector< QString >& );
|
||||
|
||||
protected:
|
||||
virtual void geometryChanged( const QRectF&, const QRectF& ) override;
|
||||
|
Loading…
x
Reference in New Issue
Block a user