2017-07-21 18:21:34 +02:00
|
|
|
/******************************************************************************
|
2018-02-06 14:55:35 +01:00
|
|
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
|
|
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
2017-07-21 18:21:34 +02:00
|
|
|
*****************************************************************************/
|
|
|
|
|
2018-03-28 09:01:25 -07:00
|
|
|
#include "QskVirtualKeyboard.h"
|
2018-04-06 17:30:24 +02:00
|
|
|
#include "QskPushButton.h"
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2018-07-19 14:10:48 +02:00
|
|
|
#include <qguiapplication.h>
|
|
|
|
#include <qset.h>
|
2018-08-03 08:15:28 +02:00
|
|
|
#include <qstylehints.h>
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
2023-03-06 08:49:53 +01:00
|
|
|
class Button : public QskPushButton
|
2018-04-06 17:30:24 +02:00
|
|
|
{
|
2018-08-03 08:15:28 +02:00
|
|
|
public:
|
2023-03-06 08:49:53 +01:00
|
|
|
Button( QskVirtualKeyboard* parent )
|
2018-08-03 08:15:28 +02:00
|
|
|
: QskPushButton( parent )
|
2018-04-06 17:30:24 +02:00
|
|
|
{
|
|
|
|
setFocusPolicy( Qt::TabFocus );
|
2023-03-06 08:49:53 +01:00
|
|
|
|
|
|
|
setSubcontrolProxy( QskPushButton::Panel, QskVirtualKeyboard::ButtonPanel );
|
|
|
|
setSubcontrolProxy( QskPushButton::Text, QskVirtualKeyboard::ButtonText );
|
2018-04-06 17:30:24 +02:00
|
|
|
}
|
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
int key() const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2023-03-06 08:49:53 +01:00
|
|
|
return m_key;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
2018-04-06 17:30:24 +02:00
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
void setKey( int key )
|
|
|
|
{
|
|
|
|
m_key = key;
|
|
|
|
}
|
2018-04-06 17:30:24 +02:00
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
private:
|
2023-03-06 08:49:53 +01:00
|
|
|
int m_key = 0;
|
2017-07-21 18:21:34 +02:00
|
|
|
};
|
2023-03-06 08:49:53 +01:00
|
|
|
|
|
|
|
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 ) );
|
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
|
|
|
|
QSK_SUBCONTROL( QskVirtualKeyboard, Panel )
|
|
|
|
QSK_SUBCONTROL( QskVirtualKeyboard, ButtonPanel )
|
|
|
|
QSK_SUBCONTROL( QskVirtualKeyboard, ButtonText )
|
|
|
|
|
|
|
|
class QskVirtualKeyboard::PrivateData
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2023-03-06 08:49:53 +01:00
|
|
|
public:
|
|
|
|
int rowCount = 5;
|
|
|
|
int columnCount = 12;
|
|
|
|
|
|
|
|
QskVirtualKeyboardLayouts layouts;
|
|
|
|
const QskVirtualKeyboardLayouts::Layout* currentLayout = nullptr;
|
|
|
|
QskVirtualKeyboard::Mode mode = QskVirtualKeyboard::LowercaseMode;
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
QVector< Button* > keyButtons;
|
|
|
|
QSet< int > keyCodes;
|
2017-07-21 18:21:34 +02:00
|
|
|
};
|
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
QskVirtualKeyboard::QskVirtualKeyboard( QQuickItem* parent )
|
|
|
|
: Inherited( parent )
|
|
|
|
, m_data( new PrivateData )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2023-03-06 08:49:53 +01:00
|
|
|
setPolishOnResize( true );
|
|
|
|
initSizePolicy( QskSizePolicy::Expanding, QskSizePolicy::Fixed );
|
|
|
|
|
|
|
|
#define LOWER( x ) int( x + 32 ) // Convert an uppercase key to lowercase
|
|
|
|
m_data->layouts =
|
|
|
|
{
|
2018-03-28 09:01:25 -07:00
|
|
|
#include "QskVirtualKeyboardLayouts.cpp"
|
2023-03-06 08:49:53 +01:00
|
|
|
};
|
2017-07-21 18:21:34 +02:00
|
|
|
#undef LOWER
|
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
ensureButtons();
|
|
|
|
|
|
|
|
connect( this, &QskControl::localeChanged,
|
|
|
|
this, &QskVirtualKeyboard::updateLocale );
|
|
|
|
|
|
|
|
updateLocale( locale() );
|
|
|
|
|
|
|
|
setSubcontrolProxy( QskBox::Panel, Panel );
|
|
|
|
}
|
|
|
|
|
|
|
|
QskVirtualKeyboard::~QskVirtualKeyboard()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void QskVirtualKeyboard::setMode( QskVirtualKeyboard::Mode mode )
|
|
|
|
{
|
|
|
|
m_data->mode = mode;
|
|
|
|
polish();
|
|
|
|
|
|
|
|
Q_EMIT modeChanged( m_data->mode );
|
|
|
|
}
|
|
|
|
|
|
|
|
QskVirtualKeyboard::Mode QskVirtualKeyboard::mode() const
|
|
|
|
{
|
|
|
|
return m_data->mode;
|
|
|
|
}
|
|
|
|
|
|
|
|
QSizeF QskVirtualKeyboard::layoutSizeHint(
|
|
|
|
Qt::SizeHint which, const QSizeF& constraint ) const
|
|
|
|
{
|
|
|
|
if ( which != Qt::PreferredSize )
|
|
|
|
return QSizeF();
|
|
|
|
|
|
|
|
const qreal ratio = qreal( rowCount() ) / columnCount();
|
|
|
|
|
|
|
|
qreal w = constraint.width();
|
|
|
|
qreal h = constraint.height();
|
|
|
|
|
|
|
|
if ( h >= 0 )
|
|
|
|
{
|
|
|
|
const auto padding = innerPadding( Panel, QSizeF( h, h ) );
|
|
|
|
const auto dw = padding.left() + padding.right();
|
|
|
|
const auto dh = padding.top() + padding.bottom();
|
|
|
|
|
|
|
|
w = ( h - dh ) / ratio + dw;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( w < 0 )
|
|
|
|
w = 600;
|
|
|
|
|
|
|
|
const auto padding = innerPadding( Panel, QSizeF( w, w ) );
|
|
|
|
const auto dw = padding.left() + padding.right();
|
|
|
|
const auto dh = padding.top() + padding.bottom();
|
|
|
|
|
|
|
|
h = ( w - dw ) * ratio + dh;
|
|
|
|
}
|
|
|
|
|
|
|
|
return QSizeF( w, h );
|
|
|
|
}
|
|
|
|
|
|
|
|
qreal QskVirtualKeyboard::keyStretch( int key ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2018-08-03 08:15:28 +02:00
|
|
|
switch ( key )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
case Qt::Key_Backspace:
|
|
|
|
case Qt::Key_Shift:
|
|
|
|
case Qt::Key_CapsLock:
|
|
|
|
return 1.5;
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
case Qt::Key_Space:
|
|
|
|
return 3.5;
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
case Qt::Key_Return:
|
|
|
|
case Qt::Key_Mode_switch:
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
// Possibly smaller
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
return 1.0;
|
|
|
|
}
|
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
bool QskVirtualKeyboard::isKeyVisible( int key ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2023-03-06 08:49:53 +01:00
|
|
|
return key != 0;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
QString QskVirtualKeyboard::textForKey( int key ) const
|
2018-03-30 01:15:05 -07:00
|
|
|
{
|
2018-04-06 17:30:24 +02:00
|
|
|
// Special cases
|
2018-08-03 08:15:28 +02:00
|
|
|
switch ( key )
|
2018-03-30 01:15:05 -07:00
|
|
|
{
|
2018-04-06 17:30:24 +02:00
|
|
|
case Qt::Key_Backspace:
|
|
|
|
case Qt::Key_Muhenkan:
|
|
|
|
return QChar( 0x232B );
|
2018-03-30 01:15:05 -07:00
|
|
|
|
2018-04-06 17:30:24 +02:00
|
|
|
case Qt::Key_CapsLock:
|
|
|
|
case Qt::Key_Kana_Lock:
|
|
|
|
return QChar( 0x21E7 );
|
2018-03-30 01:15:05 -07:00
|
|
|
|
2018-04-06 17:30:24 +02:00
|
|
|
case Qt::Key_Shift:
|
|
|
|
case Qt::Key_Kana_Shift:
|
|
|
|
return QChar( 0x2B06 );
|
2018-03-30 01:15:05 -07:00
|
|
|
|
2018-04-06 17:30:24 +02:00
|
|
|
case Qt::Key_Mode_switch:
|
|
|
|
return QChar( 0x2026 );
|
2018-03-30 01:15:05 -07:00
|
|
|
|
2018-04-06 17:30:24 +02:00
|
|
|
case Qt::Key_Return:
|
|
|
|
case Qt::Key_Kanji:
|
|
|
|
return QChar( 0x23CE );
|
2018-03-15 10:31:50 +01:00
|
|
|
|
2018-04-06 17:30:24 +02:00
|
|
|
case Qt::Key_Left:
|
|
|
|
return QChar( 0x2190 );
|
2018-03-14 17:30:37 +01:00
|
|
|
|
2018-04-06 17:30:24 +02:00
|
|
|
case Qt::Key_Right:
|
|
|
|
return QChar( 0x2192 );
|
2018-03-23 07:59:26 +01:00
|
|
|
|
2018-04-06 17:30:24 +02:00
|
|
|
case Qt::Key_ApplicationLeft:
|
|
|
|
return QChar( 0x2B05 );
|
2018-03-27 19:00:43 +02:00
|
|
|
|
2018-04-06 17:30:24 +02:00
|
|
|
case Qt::Key_ApplicationRight:
|
|
|
|
return QChar( 0x27A1 );
|
2018-03-26 10:05:44 +02:00
|
|
|
|
2018-04-06 17:30:24 +02:00
|
|
|
default:
|
|
|
|
return QChar( key );
|
2018-03-26 10:05:44 +02:00
|
|
|
}
|
2018-03-14 17:30:37 +01:00
|
|
|
}
|
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
QskVirtualKeyboard::KeyType QskVirtualKeyboard::typeForKey( int key ) const
|
2018-03-14 17:30:37 +01:00
|
|
|
{
|
2023-03-06 08:49:53 +01:00
|
|
|
switch( key )
|
|
|
|
{
|
2023-03-09 18:05:09 +01:00
|
|
|
case Qt::Key_Return:
|
|
|
|
case Qt::Key_Enter:
|
|
|
|
return EnterType;
|
2018-03-14 17:30:37 +01:00
|
|
|
|
2023-03-09 18:05:09 +01:00
|
|
|
case Qt::Key_Backspace:
|
|
|
|
return BackspaceType;
|
2018-06-03 11:01:22 +02:00
|
|
|
|
2023-03-09 18:05:09 +01:00
|
|
|
case Qt::Key_Shift:
|
|
|
|
case Qt::Key_CapsLock:
|
|
|
|
return CapsSwitchType;
|
2018-06-03 11:01:22 +02:00
|
|
|
|
2023-03-09 18:05:09 +01:00
|
|
|
case Qt::Key_Mode_switch:
|
|
|
|
return ModeSwitchType;
|
2018-06-03 11:01:22 +02:00
|
|
|
|
2023-03-09 18:05:09 +01:00
|
|
|
case Qt::Key_Comma:
|
|
|
|
case Qt::Key_Period:
|
|
|
|
return SpecialCharacterType;
|
2018-06-03 11:01:22 +02:00
|
|
|
|
2023-03-09 18:05:09 +01:00
|
|
|
default:
|
|
|
|
return NormalType;
|
2023-03-06 08:49:53 +01:00
|
|
|
}
|
2018-06-03 11:01:22 +02:00
|
|
|
}
|
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
void QskVirtualKeyboard::updateLayout() // ### fill keyCodes here
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2023-03-06 08:49:53 +01:00
|
|
|
const auto r = layoutRect();
|
|
|
|
if ( r.isEmpty() )
|
|
|
|
return;
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
const auto spacing = spacingHint( Panel );
|
|
|
|
const auto totalVSpacing = ( rowCount() - 1 ) * spacing;
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
const auto keyHeight = ( r.height() - totalVSpacing ) / rowCount();
|
2017-08-31 09:09:05 +02:00
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
qreal yPos = r.top();
|
2018-03-22 18:30:15 +01:00
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
const auto& page = ( *m_data->currentLayout )[ mode() ];
|
2018-04-01 12:47:44 +02:00
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
for ( int i = 0; i < page.size(); i++ )
|
2018-03-22 18:30:15 +01:00
|
|
|
{
|
2023-03-06 08:49:53 +01:00
|
|
|
const QVector< int > row = page[ i ];
|
|
|
|
#if 1
|
|
|
|
// there should be a better way
|
|
|
|
auto totalHSpacing = -spacing;
|
|
|
|
if ( spacing )
|
2018-03-22 18:30:15 +01:00
|
|
|
{
|
2023-03-06 08:49:53 +01:00
|
|
|
for ( int j = 0; j < row.size(); j++ )
|
|
|
|
{
|
|
|
|
if ( row[ j ] != 0 )
|
|
|
|
totalHSpacing += spacing;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
const auto baseKeyWidth = ( r.width() - totalHSpacing ) / rowStretch( row );
|
|
|
|
qreal xPos = r.left();
|
2018-03-22 18:30:15 +01:00
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
for ( int j = 0; j < columnCount(); j++ )
|
|
|
|
{
|
|
|
|
auto button = m_data->keyButtons[ i * columnCount() + j ];
|
2018-04-01 12:47:44 +02:00
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
if( j < row.size() )
|
|
|
|
{
|
|
|
|
const int key = row[ j ];
|
|
|
|
button->setVisible( isKeyVisible( key ) );
|
2018-03-22 18:30:15 +01:00
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
if ( button->isVisible() )
|
|
|
|
{
|
|
|
|
const qreal keyWidth = baseKeyWidth * keyStretch( key );
|
2018-04-06 17:30:24 +02:00
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
const QRectF rect( xPos, yPos, keyWidth, keyHeight );
|
2018-04-06 17:30:24 +02:00
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
button->setGeometry( rect );
|
|
|
|
button->setAutoRepeat( qskIsAutorepeat( key ) );
|
|
|
|
button->setKey( key );
|
|
|
|
button->setText( textForKey( key ) );
|
|
|
|
|
|
|
|
const auto type = typeForKey( key );
|
|
|
|
const auto emphasis = emphasisForType( type );
|
|
|
|
button->setEmphasis( emphasis );
|
|
|
|
|
|
|
|
xPos += keyWidth + spacing;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
button->setVisible( false );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
yPos += keyHeight + spacing;
|
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
bool QskVirtualKeyboard::hasKey( int keyCode ) const
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2023-03-06 08:49:53 +01:00
|
|
|
return m_data->keyCodes.contains( keyCode );
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
int QskVirtualKeyboard::rowCount() const
|
2018-03-22 15:48:29 +01:00
|
|
|
{
|
2023-03-06 08:49:53 +01:00
|
|
|
return m_data->rowCount;
|
2018-03-22 15:48:29 +01:00
|
|
|
}
|
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
void QskVirtualKeyboard::setRowCount( int rowCount )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2023-03-06 08:49:53 +01:00
|
|
|
m_data->rowCount = rowCount;
|
|
|
|
ensureButtons();
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
int QskVirtualKeyboard::columnCount() const
|
2018-04-18 19:41:46 +02:00
|
|
|
{
|
2023-03-06 08:49:53 +01:00
|
|
|
return m_data->columnCount;
|
|
|
|
}
|
2018-04-12 13:32:28 +02:00
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
void QskVirtualKeyboard::setColumnCount( int columnCount )
|
|
|
|
{
|
|
|
|
m_data->columnCount = columnCount;
|
|
|
|
ensureButtons();
|
|
|
|
}
|
2018-04-18 19:41:46 +02:00
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
QskVirtualKeyboardLayouts QskVirtualKeyboard::layouts() const
|
|
|
|
{
|
|
|
|
return m_data->layouts;
|
2018-04-12 12:03:51 +02:00
|
|
|
}
|
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
void QskVirtualKeyboard::setLayouts( const QskVirtualKeyboardLayouts& layouts )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2023-03-06 08:49:53 +01:00
|
|
|
m_data->layouts = layouts;
|
|
|
|
}
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
void QskVirtualKeyboard::ensureButtons()
|
|
|
|
{
|
|
|
|
const int newButtonSize = rowCount() * columnCount();
|
|
|
|
const int oldButtonSize = m_data->keyButtons.size();
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
if( newButtonSize == oldButtonSize )
|
|
|
|
return;
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
const auto autoRepeatInterval =
|
|
|
|
1000 / QGuiApplication::styleHints()->keyboardAutoRepeatRate();
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
m_data->keyButtons.reserve( rowCount() * columnCount() );
|
2017-07-21 18:21:34 +02:00
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
for( int i = 0; i < rowCount(); i++ )
|
2018-03-14 17:30:35 +01:00
|
|
|
{
|
2023-03-06 08:49:53 +01:00
|
|
|
for( int j = 0; j < columnCount(); j++ )
|
2018-04-06 18:07:12 +02:00
|
|
|
{
|
2023-03-06 08:49:53 +01:00
|
|
|
const int index = i * columnCount() + j;
|
2018-03-21 13:00:24 +01:00
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
if( index >= m_data->keyButtons.size() )
|
2018-04-06 17:30:24 +02:00
|
|
|
{
|
2023-03-06 08:49:53 +01:00
|
|
|
auto button = new Button( this );
|
|
|
|
button->installEventFilter( this );
|
2018-03-21 13:00:24 +01:00
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
button->setAutoRepeat( false );
|
|
|
|
button->setAutoRepeatDelay( 500 );
|
|
|
|
button->setAutoRepeatInterval( autoRepeatInterval );
|
2018-03-21 13:00:24 +01:00
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
connect( button, &QskPushButton::pressed,
|
|
|
|
this, &QskVirtualKeyboard::buttonPressed );
|
2018-03-21 13:00:24 +01:00
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
m_data->keyButtons += button;
|
2018-04-06 17:30:24 +02:00
|
|
|
}
|
2018-03-21 13:00:24 +01:00
|
|
|
}
|
2018-03-30 01:15:05 -07:00
|
|
|
}
|
2018-03-14 17:30:37 +01:00
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
while( m_data->keyButtons.size() > newButtonSize )
|
|
|
|
{
|
|
|
|
auto* button = m_data->keyButtons.takeLast();
|
|
|
|
button->deleteLater();
|
|
|
|
}
|
2018-06-03 11:01:22 +02:00
|
|
|
}
|
|
|
|
|
2018-04-06 17:30:24 +02:00
|
|
|
void QskVirtualKeyboard::buttonPressed()
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2018-04-06 17:30:24 +02:00
|
|
|
const auto button = static_cast< const Button* >( sender() );
|
|
|
|
if ( button == nullptr )
|
|
|
|
return;
|
2018-04-01 12:47:44 +02:00
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
const int key = button->key();
|
2017-07-21 18:21:34 +02:00
|
|
|
|
|
|
|
// Mode-switching keys
|
2018-08-03 08:15:28 +02:00
|
|
|
switch ( key )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
case Qt::Key_CapsLock:
|
|
|
|
case Qt::Key_Kana_Lock:
|
2018-04-06 09:00:09 +02:00
|
|
|
{
|
2017-07-21 18:21:34 +02:00
|
|
|
setMode( UppercaseMode ); // Lock caps
|
2018-04-06 09:00:09 +02:00
|
|
|
break;
|
|
|
|
}
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
case Qt::Key_Shift:
|
|
|
|
case Qt::Key_Kana_Shift:
|
2018-04-06 09:00:09 +02:00
|
|
|
{
|
2017-07-21 18:21:34 +02:00
|
|
|
setMode( LowercaseMode ); // Unlock caps
|
2018-04-06 09:00:09 +02:00
|
|
|
break;
|
|
|
|
}
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
case Qt::Key_Mode_switch: // Cycle through modes, but skip caps
|
2018-04-06 09:00:09 +02:00
|
|
|
{
|
2018-03-28 09:01:25 -07:00
|
|
|
setMode( static_cast< QskVirtualKeyboard::Mode >(
|
2018-04-01 12:47:44 +02:00
|
|
|
m_data->mode ? ( ( m_data->mode + 1 ) % QskVirtualKeyboard::ModeCount )
|
2018-08-03 08:15:28 +02:00
|
|
|
: SpecialCharacterMode ) );
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
break;
|
2018-04-06 09:00:09 +02:00
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
2018-04-10 16:51:35 +02:00
|
|
|
Q_EMIT keySelected( key );
|
2018-04-06 09:00:09 +02:00
|
|
|
}
|
|
|
|
}
|
2018-03-30 01:15:05 -07:00
|
|
|
}
|
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
void QskVirtualKeyboard::updateKeyCodes()
|
|
|
|
{
|
|
|
|
m_data->keyCodes = {};
|
|
|
|
m_data->keyCodes.reserve( rowCount() * columnCount() );
|
|
|
|
|
|
|
|
for ( int mode = 0; mode < ModeCount; mode++ )
|
|
|
|
{
|
|
|
|
const auto& page = ( *m_data->currentLayout )[ mode ];
|
|
|
|
|
|
|
|
for ( int i = 0; i < page.size(); i++ )
|
|
|
|
{
|
|
|
|
const auto& row = page[ i ];
|
|
|
|
|
|
|
|
for ( int j = 0; j < row.size(); j++ )
|
|
|
|
{
|
|
|
|
m_data->keyCodes += row[ j ];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
qreal QskVirtualKeyboard::rowStretch( const QVector< int >& row )
|
|
|
|
{
|
|
|
|
qreal stretch = 0;
|
|
|
|
|
|
|
|
for ( const int& key : row )
|
|
|
|
{
|
|
|
|
if ( !key )
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
stretch += keyStretch( key );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( stretch == 0.0 )
|
|
|
|
{
|
|
|
|
stretch = columnCount();
|
|
|
|
}
|
|
|
|
|
|
|
|
return stretch;
|
|
|
|
}
|
|
|
|
|
2018-03-28 09:01:25 -07:00
|
|
|
void QskVirtualKeyboard::updateLocale( const QLocale& locale )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2018-06-03 11:01:22 +02:00
|
|
|
const QskVirtualKeyboardLayouts::Layout* newLayout = nullptr;
|
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
switch ( locale.language() )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
|
|
|
case QLocale::Bulgarian:
|
2023-03-06 08:49:53 +01:00
|
|
|
newLayout = &m_data->layouts.bg;
|
2017-07-21 18:21:34 +02:00
|
|
|
break;
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
case QLocale::Czech:
|
2023-03-06 08:49:53 +01:00
|
|
|
newLayout = &m_data->layouts.cs;
|
2017-07-21 18:21:34 +02:00
|
|
|
break;
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
case QLocale::German:
|
2023-03-06 08:49:53 +01:00
|
|
|
newLayout = &m_data->layouts.de;
|
2017-07-21 18:21:34 +02:00
|
|
|
break;
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
case QLocale::Danish:
|
2023-03-06 08:49:53 +01:00
|
|
|
newLayout = &m_data->layouts.da;
|
2017-07-21 18:21:34 +02:00
|
|
|
break;
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
case QLocale::Greek:
|
2023-03-06 08:49:53 +01:00
|
|
|
newLayout = &m_data->layouts.el;
|
2017-07-21 18:21:34 +02:00
|
|
|
break;
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
case QLocale::English:
|
2018-04-01 12:47:44 +02:00
|
|
|
{
|
2018-08-03 08:15:28 +02:00
|
|
|
switch ( locale.country() )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2018-04-01 12:47:44 +02:00
|
|
|
case QLocale::Canada:
|
|
|
|
case QLocale::UnitedStates:
|
|
|
|
case QLocale::UnitedStatesMinorOutlyingIslands:
|
|
|
|
case QLocale::UnitedStatesVirginIslands:
|
2023-03-06 08:49:53 +01:00
|
|
|
newLayout = &m_data->layouts.en_US;
|
2018-04-01 12:47:44 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2023-03-06 08:49:53 +01:00
|
|
|
newLayout = &m_data->layouts.en_GB;
|
2018-04-01 12:47:44 +02:00
|
|
|
break;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
2018-03-14 17:30:35 +01:00
|
|
|
|
2018-04-01 12:47:44 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
case QLocale::Spanish:
|
2023-03-06 08:49:53 +01:00
|
|
|
newLayout = &m_data->layouts.es;
|
2017-07-21 18:21:34 +02:00
|
|
|
break;
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
case QLocale::Finnish:
|
2023-03-06 08:49:53 +01:00
|
|
|
newLayout = &m_data->layouts.fi;
|
2017-07-21 18:21:34 +02:00
|
|
|
break;
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
case QLocale::French:
|
2023-03-06 08:49:53 +01:00
|
|
|
newLayout = &m_data->layouts.fr;
|
2017-07-21 18:21:34 +02:00
|
|
|
break;
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
case QLocale::Hungarian:
|
2023-03-06 08:49:53 +01:00
|
|
|
newLayout = &m_data->layouts.hu;
|
2017-07-21 18:21:34 +02:00
|
|
|
break;
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
case QLocale::Italian:
|
2023-03-06 08:49:53 +01:00
|
|
|
newLayout = &m_data->layouts.it;
|
2017-07-21 18:21:34 +02:00
|
|
|
break;
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
case QLocale::Japanese:
|
2023-03-06 08:49:53 +01:00
|
|
|
newLayout = &m_data->layouts.ja;
|
2017-07-21 18:21:34 +02:00
|
|
|
break;
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
case QLocale::Latvian:
|
2023-03-06 08:49:53 +01:00
|
|
|
newLayout = &m_data->layouts.lv;
|
2017-07-21 18:21:34 +02:00
|
|
|
break;
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
case QLocale::Lithuanian:
|
2023-03-06 08:49:53 +01:00
|
|
|
newLayout = &m_data->layouts.lt;
|
2017-07-21 18:21:34 +02:00
|
|
|
break;
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
case QLocale::Dutch:
|
2023-03-06 08:49:53 +01:00
|
|
|
newLayout = &m_data->layouts.nl;
|
2017-07-21 18:21:34 +02:00
|
|
|
break;
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
case QLocale::Portuguese:
|
2023-03-06 08:49:53 +01:00
|
|
|
newLayout = &m_data->layouts.pt;
|
2017-07-21 18:21:34 +02:00
|
|
|
break;
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
case QLocale::Romanian:
|
2023-03-06 08:49:53 +01:00
|
|
|
newLayout = &m_data->layouts.ro;
|
2017-07-21 18:21:34 +02:00
|
|
|
break;
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2018-08-03 08:15:28 +02:00
|
|
|
case QLocale::Russian:
|
2023-03-06 08:49:53 +01:00
|
|
|
newLayout = &m_data->layouts.ru;
|
2017-07-21 18:21:34 +02:00
|
|
|
break;
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
case QLocale::Slovenian:
|
2023-03-06 08:49:53 +01:00
|
|
|
newLayout = &m_data->layouts.sl;
|
2017-07-21 18:21:34 +02:00
|
|
|
break;
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
case QLocale::Slovak:
|
2023-03-06 08:49:53 +01:00
|
|
|
newLayout = &m_data->layouts.sk;
|
2017-07-21 18:21:34 +02:00
|
|
|
break;
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
case QLocale::Turkish:
|
2023-03-06 08:49:53 +01:00
|
|
|
newLayout = &m_data->layouts.tr;
|
2017-07-21 18:21:34 +02:00
|
|
|
break;
|
2017-10-17 19:02:02 +02:00
|
|
|
|
2017-07-21 18:21:34 +02:00
|
|
|
case QLocale::Chinese:
|
2023-03-06 08:49:53 +01:00
|
|
|
newLayout = &m_data->layouts.zh;
|
2017-07-21 18:21:34 +02:00
|
|
|
break;
|
2018-03-28 09:01:25 -07:00
|
|
|
#if 1
|
|
|
|
case QLocale::C:
|
2023-03-06 08:49:53 +01:00
|
|
|
newLayout = &m_data->layouts.en_US;
|
2018-03-28 09:01:25 -07:00
|
|
|
break;
|
|
|
|
#endif
|
2017-12-11 08:58:57 +01:00
|
|
|
default:
|
2018-06-03 11:01:22 +02:00
|
|
|
qWarning() << "QskVirtualKeyboard: unsupported locale:" << locale;
|
2023-03-06 08:49:53 +01:00
|
|
|
newLayout = &m_data->layouts.en_US;
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2018-06-03 11:01:22 +02:00
|
|
|
if ( newLayout != m_data->currentLayout )
|
|
|
|
{
|
|
|
|
m_data->currentLayout = newLayout;
|
2023-03-06 08:49:53 +01:00
|
|
|
updateKeyCodes();
|
2018-06-03 11:01:22 +02:00
|
|
|
|
|
|
|
setMode( LowercaseMode );
|
|
|
|
polish();
|
2023-03-06 08:49:53 +01:00
|
|
|
Q_EMIT keyboardLayoutChanged();
|
2018-06-03 11:01:22 +02:00
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2023-03-06 08:49:53 +01:00
|
|
|
QskPushButton::Emphasis QskVirtualKeyboard::emphasisForType( KeyType type )
|
2017-07-21 18:21:34 +02:00
|
|
|
{
|
2023-03-06 08:49:53 +01:00
|
|
|
switch( type )
|
|
|
|
{
|
2023-03-09 18:05:09 +01:00
|
|
|
case EnterType:
|
|
|
|
return QskPushButton::VeryHighEmphasis;
|
2018-04-06 09:00:09 +02:00
|
|
|
|
2023-03-09 18:05:09 +01:00
|
|
|
case BackspaceType:
|
|
|
|
case CapsSwitchType:
|
|
|
|
return QskPushButton::HighEmphasis;
|
2023-03-06 08:49:53 +01:00
|
|
|
|
2023-03-09 18:05:09 +01:00
|
|
|
case ModeSwitchType:
|
|
|
|
return QskPushButton::LowEmphasis;
|
2023-03-06 08:49:53 +01:00
|
|
|
|
2023-03-09 18:05:09 +01:00
|
|
|
case SpecialCharacterType:
|
|
|
|
return QskPushButton::VeryLowEmphasis;
|
2023-03-06 08:49:53 +01:00
|
|
|
|
2023-03-09 18:05:09 +01:00
|
|
|
default:
|
|
|
|
return QskPushButton::NoEmphasis;
|
2023-03-06 08:49:53 +01:00
|
|
|
}
|
2017-07-21 18:21:34 +02:00
|
|
|
}
|
|
|
|
|
2018-03-28 09:01:25 -07:00
|
|
|
#include "moc_QskVirtualKeyboard.cpp"
|