Merge branch 'master' into cmake

This commit is contained in:
Uwe Rathmann 2023-03-09 18:05:28 +01:00
commit 25f054e694
15 changed files with 1029 additions and 988 deletions

View File

@ -7,6 +7,7 @@
#include <QskComboBox.h> #include <QskComboBox.h>
#include <QskSegmentedBar.h> #include <QskSegmentedBar.h>
#include <QskLabelData.h>
namespace namespace
{ {

View File

@ -14,98 +14,172 @@
#include <QskTextInput.h> #include <QskTextInput.h>
#include <QskAspect.h> #include <QskAspect.h>
#include <QskWindow.h>
#include <QskFunctions.h> #include <QskFunctions.h>
#include <QskInputPanelBox.h>
#include <QskObjectCounter.h> #include <QskObjectCounter.h>
#include <QskVirtualKeyboard.h>
#include <QskWindow.h>
#include <QFontMetricsF> #include <QFontMetricsF>
#include <QGuiApplication> #include <QGuiApplication>
static inline QString nativeLocaleString( const QLocale& locale ) namespace
{ {
switch ( locale.language() ) class Keyboard final : public QskVirtualKeyboard
{ {
case QLocale::Bulgarian: using Inherited = QskVirtualKeyboard;
return QStringLiteral( "български език" );
case QLocale::Czech: public:
return QStringLiteral( "Čeština" ); Keyboard( QQuickItem* parentItem = nullptr ):
QskVirtualKeyboard( parentItem )
case QLocale::German:
return QStringLiteral( "Deutsch" );
case QLocale::Danish:
return QStringLiteral( "Dansk" );
case QLocale::Greek:
return QStringLiteral( "Eλληνικά" );
case QLocale::English:
{
switch ( locale.country() )
{ {
case QLocale::Canada: // here rearrange keyboard layouts if necessary
case QLocale::UnitedStates:
case QLocale::UnitedStatesMinorOutlyingIslands:
case QLocale::UnitedStatesVirginIslands:
return QStringLiteral( "English (US)" );
default:
return QStringLiteral( "English (UK)" );
} }
};
class Panel : public QskInputPanel
{
public:
Panel( QQuickItem* parentItem = nullptr )
: QskInputPanel( parentItem )
{
setAutoLayoutChildren( true );
setLayoutAlignmentHint( Qt::AlignHCenter | Qt::AlignBottom );
m_box = new QskInputPanelBox( this );
m_box->setKeyboard( new Keyboard() );
connect( m_box, &QskInputPanelBox::keySelected,
this, &QskInputPanel::keySelected );
connect( m_box, &QskInputPanelBox::predictiveTextSelected,
this, &QskInputPanel::predictiveTextSelected );
} }
case QLocale::Spanish: void attachItem( QQuickItem* item ) override
return QStringLiteral( "Español" ); {
m_box->attachInputItem( item );
}
case QLocale::Finnish: QQuickItem* inputProxy() const override
return QStringLiteral( "Suomi" ); {
return m_box->inputProxy();
}
case QLocale::French: void setPrompt( const QString& prompt ) override
return QStringLiteral( "Français" ); {
m_box->setInputPrompt( prompt );
}
case QLocale::Hungarian: void setPredictionEnabled( bool on ) override
return QStringLiteral( "Magyar" ); {
m_box->setPanelHint( QskInputPanelBox::Prediction, on );
}
case QLocale::Italian: void setPrediction( const QStringList& prediction ) override
return QStringLiteral( "Italiano" ); {
QskInputPanel::setPrediction( prediction );
m_box->setPrediction( prediction );
}
case QLocale::Japanese:
return QStringLiteral( "日本語" );
case QLocale::Latvian: private:
return QStringLiteral( "Latviešu" ); QskInputPanelBox* m_box;
};
case QLocale::Lithuanian: class InputContextFactory : public QskInputContextFactory
return QStringLiteral( "Lietuvių" ); {
QskInputPanel* createPanel() const override
{
return new Panel;
}
};
case QLocale::Dutch: QString nativeLocaleString( const QLocale& locale )
return QStringLiteral( "Nederlands" ); {
switch ( locale.language() )
{
case QLocale::Bulgarian:
return QStringLiteral( "български език" );
case QLocale::Portuguese: case QLocale::Czech:
return QStringLiteral( "Português" ); return QStringLiteral( "Čeština" );
case QLocale::Romanian: case QLocale::German:
return QStringLiteral( "Română" ); return QStringLiteral( "Deutsch" );
case QLocale::Russian: case QLocale::Danish:
return QStringLiteral( "Русский" ); return QStringLiteral( "Dansk" );
case QLocale::Slovenian: case QLocale::Greek:
return QStringLiteral( "Slovenščina" ); return QStringLiteral( "Eλληνικά" );
case QLocale::Slovak: case QLocale::English:
return QStringLiteral( "Slovenčina" ); {
switch ( locale.country() )
{
case QLocale::Canada:
case QLocale::UnitedStates:
case QLocale::UnitedStatesMinorOutlyingIslands:
case QLocale::UnitedStatesVirginIslands:
return QStringLiteral( "English (US)" );
case QLocale::Turkish: default:
return QStringLiteral( "Türkçe" ); return QStringLiteral( "English (UK)" );
}
}
case QLocale::Chinese: case QLocale::Spanish:
return QStringLiteral( "中文" ); return QStringLiteral( "Español" );
default: case QLocale::Finnish:
return QLocale::languageToString( locale.language() ); return QStringLiteral( "Suomi" );
case QLocale::French:
return QStringLiteral( "Français" );
case QLocale::Hungarian:
return QStringLiteral( "Magyar" );
case QLocale::Italian:
return QStringLiteral( "Italiano" );
case QLocale::Japanese:
return QStringLiteral( "日本語" );
case QLocale::Latvian:
return QStringLiteral( "Latviešu" );
case QLocale::Lithuanian:
return QStringLiteral( "Lietuvių" );
case QLocale::Dutch:
return QStringLiteral( "Nederlands" );
case QLocale::Portuguese:
return QStringLiteral( "Português" );
case QLocale::Romanian:
return QStringLiteral( "Română" );
case QLocale::Russian:
return QStringLiteral( "Русский" );
case QLocale::Slovenian:
return QStringLiteral( "Slovenščina" );
case QLocale::Slovak:
return QStringLiteral( "Slovenčina" );
case QLocale::Turkish:
return QStringLiteral( "Türkçe" );
case QLocale::Chinese:
return QStringLiteral( "中文" );
default:
return QLocale::languageToString( locale.language() );
}
} }
} }
@ -306,6 +380,7 @@ int main( int argc, char* argv[] )
window2.show(); window2.show();
#endif #endif
QskInputContext::instance()->setFactory( new InputContextFactory() );
return app.exec(); return app.exec();
} }

View File

@ -1103,9 +1103,23 @@ void Editor::setupVirtualKeyboard()
// key panel // key panel
setMargin( Q::ButtonPanel, 5_dp ); setMargin( Q::ButtonPanel, 5_dp );
setGradient( Q::ButtonPanel, m_pal.background ); setGradient( Q::ButtonPanel, m_pal.surface2 );
setGradient( Q::ButtonPanel | QskPushButton::Pressed, m_pal.surface );
setColor( Q::ButtonText | QskPushButton::Pressed, m_pal.outlineVariant );
setBoxShape( Q::ButtonPanel, 6_dp ); setBoxShape( Q::ButtonPanel, 6_dp );
setBoxShape( Q::ButtonPanel | A::Huge, 100, Qt::RelativeSize );
setGradient( Q::ButtonPanel | A::Huge, m_pal.primary );
setColor( Q::ButtonText | A::Huge, m_pal.onPrimary );
setGradient( Q::ButtonPanel | A::Large, m_pal.outlineVariant );
setBoxShape( Q::ButtonPanel | A::Small, 100, Qt::RelativeSize );
setGradient( Q::ButtonPanel | A::Small, m_pal.secondary );
setColor( Q::ButtonText | A::Small, m_pal.onSecondary );
setGradient( Q::ButtonPanel | A::Tiny, m_pal.outlineVariant );
for ( auto state : { A::NoState, Q::Focused } ) for ( auto state : { A::NoState, Q::Focused } )
setBoxBorderColors( Q::ButtonPanel | QskPushButton::Pressed | state, setBoxBorderColors( Q::ButtonPanel | QskPushButton::Pressed | state,
m_pal.secondary ); m_pal.secondary );
@ -1117,7 +1131,7 @@ void Editor::setupVirtualKeyboard()
setFontRole( Q::ButtonText, QskMaterial3Skin::M3HeadlineSmall ); setFontRole( Q::ButtonText, QskMaterial3Skin::M3HeadlineSmall );
// panel // panel
setGradient( Q::Panel, m_pal.surfaceVariant ); setGradient( Q::Panel, m_pal.background );
setPadding( Q::Panel, { 3_dp, 25_dp, 3_dp, 5_dp } ); setPadding( Q::Panel, { 3_dp, 25_dp, 3_dp, 5_dp } );
} }

View File

@ -20,6 +20,11 @@ static void qskRegisterLabelData()
Q_CONSTRUCTOR_FUNCTION( qskRegisterLabelData ) Q_CONSTRUCTOR_FUNCTION( qskRegisterLabelData )
QskLabelData::QskLabelData( const char* text )
: m_text( text )
{
}
QskLabelData::QskLabelData( const QString& text ) QskLabelData::QskLabelData( const QString& text )
: m_text( text ) : m_text( text )
{ {

View File

@ -23,6 +23,7 @@ class QSK_EXPORT QskLabelData
public: public:
QskLabelData() = default; QskLabelData() = default;
QskLabelData( const char* );
QskLabelData( const QString& ); QskLabelData( const QString& );
QskLabelData( const QskIcon& ); QskLabelData( const QskIcon& );
QskLabelData( const QString&, const QskIcon& ); QskLabelData( const QString&, const QskIcon& );

View File

@ -5,8 +5,7 @@
#include "QskComboBox.h" #include "QskComboBox.h"
#include "QskGraphicProvider.h" #include "QskLabelData.h"
#include "QskGraphic.h"
#include "QskMenu.h" #include "QskMenu.h"
#include "QskTextOptions.h" #include "QskTextOptions.h"
#include "QskEvent.h" #include "QskEvent.h"
@ -60,41 +59,12 @@ static inline int qskFindOption( QskComboBox* comboBox, const QString& key )
return -1; return -1;
} }
namespace
{
class Option
{
public:
Option( const QskGraphic& graphic, const QString& text )
: text( text )
, graphic( graphic )
{
}
Option( const QUrl& graphicSource, const QString& text )
: graphicSource( graphicSource )
, text( text )
{
#if 1
// lazy loading TODO ...
if( !graphicSource.isEmpty() )
graphic = Qsk::loadGraphic( graphicSource );
#endif
}
QUrl graphicSource;
QString text;
QskGraphic graphic;
};
}
class QskComboBox::PrivateData class QskComboBox::PrivateData
{ {
public: public:
QPointer < QskMenu > menu; QPointer < QskMenu > menu;
QVector< Option > options; QVector< QskLabelData > options;
QString placeholderText; QString placeholderText;
int currentIndex = -1; int currentIndex = -1;
@ -113,7 +83,6 @@ QskComboBox::QskComboBox( QQuickItem* parent )
setFocusPolicy( Qt::StrongFocus ); setFocusPolicy( Qt::StrongFocus );
setAcceptHoverEvents( true ); setAcceptHoverEvents( true );
} }
QskComboBox::~QskComboBox() QskComboBox::~QskComboBox()
@ -138,17 +107,6 @@ bool QskComboBox::isPopupOpen() const
return hasSkinState( PopupOpen ); return hasSkinState( PopupOpen );
} }
QskGraphic QskComboBox::icon() const
{
if( m_data->currentIndex >= 0 )
{
const auto option = optionAt( m_data->currentIndex );
return option.at( 0 ).value< QskGraphic >();
}
return QskGraphic();
}
void QskComboBox::setTextOptions( const QskTextOptions& textOptions ) void QskComboBox::setTextOptions( const QskTextOptions& textOptions )
{ {
setTextOptionsHint( Text, textOptions ); setTextOptionsHint( Text, textOptions );
@ -159,52 +117,51 @@ QskTextOptions QskComboBox::textOptions() const
return textOptionsHint( Text ); return textOptionsHint( Text );
} }
void QskComboBox::addOption( const QString& text ) int QskComboBox::addOption( const QString& graphicSource, const QString& text )
{ {
addOption( QUrl(), text ); return addOption( QskLabelData( text, QskIcon( graphicSource ) ) );
} }
void QskComboBox::addOption( const QskGraphic& graphic, const QString& text ) int QskComboBox::addOption( const QUrl& graphicSource, const QString& text )
{ {
m_data->options += Option( graphic, text ); return addOption( QskLabelData( text, QskIcon( graphicSource ) ) );
}
int QskComboBox::addOption( const QskLabelData& option )
{
m_data->options += option;
resetImplicitSize(); resetImplicitSize();
update(); update();
if ( isComponentComplete() ) if ( isComponentComplete() )
Q_EMIT countChanged( count() ); Q_EMIT optionsChanged();
return count() - 1;
} }
void QskComboBox::addOption( const QString& graphicSource, const QString& text ) void QskComboBox::setOptions( const QVector< QskLabelData >& options )
{ {
addOption( QUrl( graphicSource ), text ); if ( options == m_data->options )
} return;
void QskComboBox::addOption( const QUrl& graphicSource, const QString& text ) m_data->options = options;
{ m_data->currentIndex = -1; // currentIndexChanged ???
m_data->options += Option( graphicSource, text );
resetImplicitSize(); resetImplicitSize();
update(); update();
if ( isComponentComplete() ) Q_EMIT optionsChanged();
Q_EMIT countChanged( count() );
} }
QVariantList QskComboBox::optionAt( int index ) const QVector< QskLabelData > QskComboBox::options() const
{ {
const auto& options = m_data->options; return m_data->options;
}
if( index < 0 || index >= options.count() ) QskLabelData QskComboBox::optionAt( int index ) const
return QVariantList(); {
return m_data->options.value( index );
const auto& option = options[ index ];
QVariantList list;
list += QVariant::fromValue( option.graphic );
list += QVariant::fromValue( option.text );
return list;
} }
QString QskComboBox::placeholderText() const QString QskComboBox::placeholderText() const
@ -228,16 +185,13 @@ void QskComboBox::setPlaceholderText( const QString& text )
QString QskComboBox::textAt( int index ) const QString QskComboBox::textAt( int index ) const
{ {
if ( index >= 0 && index < m_data->options.count() ) return optionAt( index ).text();
return m_data->options[ index ].text;
return QString();
} }
QString QskComboBox::currentText() const QString QskComboBox::currentText() const
{ {
if( m_data->currentIndex >= 0 ) if( m_data->currentIndex >= 0 && m_data->currentIndex < m_data->options.count() )
return m_data->options[ m_data->currentIndex ].text; return m_data->options[ m_data->currentIndex ].text();
return m_data->placeholderText; return m_data->placeholderText;
} }
@ -265,7 +219,7 @@ void QskComboBox::openPopup()
menu->setFixedWidth( cr.width() ); menu->setFixedWidth( cr.width() );
for ( const auto& option : m_data->options ) for ( const auto& option : m_data->options )
menu->addOption( option.graphic, option.text ); menu->addOption( option.icon().graphic(), option.text() );
connect( menu, &QskMenu::currentIndexChanged, connect( menu, &QskMenu::currentIndexChanged,
this, &QskComboBox::indexInPopupChanged ); this, &QskComboBox::indexInPopupChanged );
@ -391,8 +345,15 @@ void QskComboBox::clear()
{ {
m_data->options.clear(); m_data->options.clear();
if ( isComponentComplete() ) Q_EMIT optionsChanged();
Q_EMIT countChanged( count() );
if ( m_data->currentIndex >= 0 )
{
m_data->currentIndex = -1;
Q_EMIT currentIndexChanged( m_data->currentIndex );
}
update();
} }
} }

View File

@ -8,19 +8,22 @@
#include "QskControl.h" #include "QskControl.h"
class QskGraphic; class QskLabelData;
class QSK_EXPORT QskComboBox : public QskControl class QSK_EXPORT QskComboBox : public QskControl
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY( QVector< QskLabelData > options READ options
WRITE setOptions NOTIFY optionsChanged )
Q_PROPERTY( int currentIndex READ currentIndex Q_PROPERTY( int currentIndex READ currentIndex
WRITE setCurrentIndex NOTIFY currentIndexChanged ) WRITE setCurrentIndex NOTIFY currentIndexChanged )
Q_PROPERTY( QString currentText READ currentText Q_PROPERTY( QString currentText READ currentText
NOTIFY currentIndexChanged ) NOTIFY currentIndexChanged )
Q_PROPERTY( int count READ count NOTIFY countChanged ) Q_PROPERTY( int count READ count )
Q_PROPERTY( QString placeholderText READ placeholderText Q_PROPERTY( QString placeholderText READ placeholderText
WRITE setPlaceholderText NOTIFY placeholderTextChanged ) WRITE setPlaceholderText NOTIFY placeholderTextChanged )
@ -41,15 +44,17 @@ class QSK_EXPORT QskComboBox : public QskControl
void setPopupOpen( bool ); void setPopupOpen( bool );
bool isPopupOpen() const; bool isPopupOpen() const;
QskGraphic icon() const;
void setTextOptions( const QskTextOptions& ); void setTextOptions( const QskTextOptions& );
QskTextOptions textOptions() const; QskTextOptions textOptions() const;
void addOption( const QString& text ); int addOption( const QUrl&, const QString& );
void addOption( const QUrl& iconSource, const QString& text ); int addOption( const QString&, const QString& );
void addOption( const QString& iconSource, const QString& text ); int addOption( const QskLabelData& );
void addOption( const QskGraphic&, const QString& text );
void setOptions( const QVector< QskLabelData >& );
QVector< QskLabelData > options() const;
QskLabelData optionAt( int ) const;
void clear(); void clear();
@ -60,7 +65,6 @@ class QSK_EXPORT QskComboBox : public QskControl
virtual int indexInPopup() const; virtual int indexInPopup() const;
int count() const; int count() const;
QVariantList optionAt( int ) const;
QString textAt( int ) const; QString textAt( int ) const;
QString placeholderText() const; QString placeholderText() const;
@ -73,7 +77,7 @@ class QSK_EXPORT QskComboBox : public QskControl
void currentIndexChanged( int ); void currentIndexChanged( int );
void indexInPopupChanged( int ); void indexInPopupChanged( int );
void countChanged( int ); void optionsChanged();
void placeholderTextChanged( const QString& ); void placeholderTextChanged( const QString& );
protected: protected:

View File

@ -7,43 +7,13 @@
#include "QskComboBox.h" #include "QskComboBox.h"
#include "QskGraphic.h" #include "QskGraphic.h"
#include "QskLabelData.h"
#include "QskSGNode.h" #include "QskSGNode.h"
#include "QskSubcontrolLayoutEngine.h" #include "QskSubcontrolLayoutEngine.h"
namespace namespace
{ {
#if 1 // unify with the implementation from QskMenu
template< class T >
static inline QVariant qskSampleAt( const QskComboBox* box )
{
if( std::is_same< T, QString >() )
{
return box->currentText();
}
const int index = box->currentIndex();
if( index < 0 )
return QVariant::fromValue( T() );
const auto list = box->optionAt( index );
for ( const auto& value : list )
{
if ( value.canConvert< T >() )
return value;
}
return QVariant();
}
template< class T >
static inline T qskValueAt( const QskComboBox* box )
{
const auto sample = qskSampleAt< T >( box );
return sample.template value< T >();
}
#endif
class LayoutEngine : public QskSubcontrolLayoutEngine class LayoutEngine : public QskSubcontrolLayoutEngine
{ {
public: public:
@ -52,12 +22,27 @@ namespace
{ {
setSpacing( box->spacingHint( QskComboBox::Panel ) ); setSpacing( box->spacingHint( QskComboBox::Panel ) );
QSizeF graphicSize;
QString text;
if ( box->currentIndex() >= 0 )
{
const auto option = box->optionAt( box->currentIndex() );
graphicSize = option.icon().graphic().defaultSize();
text = option.text();
}
else
{
text = box->placeholderText();
}
setGraphicTextElements( box, setGraphicTextElements( box,
QskComboBox::Text, qskValueAt< QString >( box ), QskComboBox::Text, text, QskComboBox::Icon, graphicSize );
QskComboBox::Icon, qskValueAt< QskGraphic >( box ).defaultSize() );
const auto alignment = box->alignmentHint( const auto alignment = box->alignmentHint(
QskComboBox::Panel, Qt::AlignLeft ); QskComboBox::Panel, Qt::AlignLeft );
setFixedContent( QskComboBox::Text, Qt::Horizontal, alignment ); setFixedContent( QskComboBox::Text, Qt::Horizontal, alignment );
} }
}; };
@ -115,7 +100,11 @@ QSGNode* QskComboBoxSkinlet::updateSubNode(
return updateBoxNode( box, node, Q::Panel ); return updateBoxNode( box, node, Q::Panel );
case IconRole: case IconRole:
return updateGraphicNode( box, node, box->icon(), Q::Icon ); {
const auto option = box->optionAt( box->currentIndex() );
return updateGraphicNode( box, node,
option.icon().graphic(), Q::Icon );
}
case TextRole: case TextRole:
return updateTextNode( box, node ); return updateTextNode( box, node );

View File

@ -131,6 +131,7 @@ void QskSegmentedBar::setOptions( const QVector< QskLabelData >& options )
resetImplicitSize(); resetImplicitSize();
update(); update();
// selectedIndex ???
Q_EMIT optionsChanged(); Q_EMIT optionsChanged();
} }

View File

@ -12,7 +12,6 @@
#include <qstring.h> #include <qstring.h>
class QskTextOptions; class QskTextOptions;
class QskGraphic;
class QskLabelData; class QskLabelData;
class QSK_EXPORT QskSegmentedBar : public QskControl class QSK_EXPORT QskSegmentedBar : public QskControl

View File

@ -218,6 +218,20 @@ void QskInputPanelBox::setPrediction( const QStringList& prediction )
m_data->predictionBar->setPrediction( prediction ); m_data->predictionBar->setPrediction( prediction );
} }
void QskInputPanelBox::setKeyboard( QskVirtualKeyboard* keyboard )
{
if( m_data->keyboard )
{
m_data->keyboard->deleteLater();
}
m_data->keyboard = keyboard;
m_data->layout->addItem( m_data->keyboard );
connect( m_data->keyboard, &QskVirtualKeyboard::keySelected,
this, &QskInputPanelBox::keySelected );
}
void QskInputPanelBox::keyPressEvent( QKeyEvent* event ) void QskInputPanelBox::keyPressEvent( QKeyEvent* event )
{ {
int keyCode = -1; int keyCode = -1;

View File

@ -9,6 +9,7 @@
#include "QskBox.h" #include "QskBox.h"
class QskInputEngine; class QskInputEngine;
class QskVirtualKeyboard;
class QString; class QString;
class QLocale; class QLocale;
@ -52,6 +53,8 @@ class QSK_EXPORT QskInputPanelBox : public QskBox
QString inputPrompt() const; QString inputPrompt() const;
void setKeyboard( QskVirtualKeyboard* );
Q_SIGNALS: Q_SIGNALS:
void panelHintsChanged(); void panelHintsChanged();
void inputPromptChanged( const QString& ); void inputPromptChanged( const QString& );

View File

@ -5,7 +5,6 @@
#include "QskVirtualKeyboard.h" #include "QskVirtualKeyboard.h"
#include "QskPushButton.h" #include "QskPushButton.h"
#include "QskTextOptions.h"
#include <qguiapplication.h> #include <qguiapplication.h>
#include <qset.h> #include <qset.h>
@ -13,97 +12,138 @@
namespace namespace
{ {
enum class Button : public QskPushButton
{
RowCount = 5,
ColumnCount = 12
};
using KeyRow = int[ ColumnCount ];
class Button final : public QskPushButton
{ {
public: public:
Button( int row, int column, QskVirtualKeyboard* parent ) Button( QskVirtualKeyboard* parent )
: QskPushButton( parent ) : QskPushButton( parent )
, m_row( row )
, m_column( column )
{ {
#if 0
QskTextOptions options;
options.setFontSizeMode( QskTextOptions::VerticalFit );
setTextOptions( options );
#endif
setFocusPolicy( Qt::TabFocus ); setFocusPolicy( Qt::TabFocus );
setSubcontrolProxy( QskPushButton::Panel, QskVirtualKeyboard::ButtonPanel );
setSubcontrolProxy( QskPushButton::Text, QskVirtualKeyboard::ButtonText );
} }
QskAspect::Subcontrol substitutedSubcontrol( int key() const
QskAspect::Subcontrol subControl ) const override
{ {
auto keyBoard = static_cast< const QskVirtualKeyboard* >( parent() ); return m_key;
if ( subControl == QskPushButton::Panel )
return keyBoard->effectiveSubcontrol( QskVirtualKeyboard::ButtonPanel );
if ( subControl == QskPushButton::Text )
return keyBoard->effectiveSubcontrol( QskVirtualKeyboard::ButtonText );
return QskPushButton::substitutedSubcontrol( subControl );
} }
int row() const { return m_row; } void setKey( int key )
int column() const { return m_column; } {
m_key = key;
}
private: private:
const int m_row; int m_key = 0;
const int m_column;
}; };
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 ) );
}
} }
struct QskVirtualKeyboardLayouts
QSK_SUBCONTROL( QskVirtualKeyboard, Panel )
QSK_SUBCONTROL( QskVirtualKeyboard, ButtonPanel )
QSK_SUBCONTROL( QskVirtualKeyboard, ButtonText )
class QskVirtualKeyboard::PrivateData
{ {
struct KeyCodes public:
{ int rowCount = 5;
using Row = int[ ColumnCount ]; int columnCount = 12;
Row data[ RowCount ];
};
using Layout = KeyCodes[ QskVirtualKeyboard::ModeCount ]; QskVirtualKeyboardLayouts layouts;
const QskVirtualKeyboardLayouts::Layout* currentLayout = nullptr;
QskVirtualKeyboard::Mode mode = QskVirtualKeyboard::LowercaseMode;
Layout bg; // Bulgarian QVector< Button* > keyButtons;
Layout cs; // Czech QSet< int > keyCodes;
Layout de; // German
Layout da; // Danish
Layout el; // Greek
Layout en_GB; // English (GB)
Layout en_US; // English (US)
Layout es; // Spanish
Layout fi; // Finnish
Layout fr; // French
Layout hu; // Hungarian
Layout it; // Italian
Layout ja; // Japanese
Layout lv; // Latvian
Layout lt; // Lithuanian
Layout nl; // Dutch
Layout pt; // Portuguese
Layout ro; // Romanian
Layout ru; // Russian
Layout sl; // Slovene
Layout sk; // Slovak
Layout tr; // Turkish
Layout zh; // Chinese
}; };
QskVirtualKeyboard::QskVirtualKeyboard( QQuickItem* parent )
: Inherited( parent )
, m_data( new PrivateData )
{
setPolishOnResize( true );
initSizePolicy( QskSizePolicy::Expanding, QskSizePolicy::Fixed );
#define LOWER( x ) int( x + 32 ) // Convert an uppercase key to lowercase #define LOWER( x ) int( x + 32 ) // Convert an uppercase key to lowercase
static constexpr const QskVirtualKeyboardLayouts qskKeyboardLayouts = m_data->layouts =
{ {
#include "QskVirtualKeyboardLayouts.cpp" #include "QskVirtualKeyboardLayouts.cpp"
}; };
#undef LOWER #undef LOWER
static qreal qskKeyStretch( int key ) 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
{ {
switch ( key ) switch ( key )
{ {
@ -126,29 +166,12 @@ static qreal qskKeyStretch( int key )
return 1.0; return 1.0;
} }
static qreal qskRowStretch( const KeyRow& keyRow ) bool QskVirtualKeyboard::isKeyVisible( int key ) const
{ {
qreal stretch = 0; return key != 0;
for ( const auto& key : keyRow )
{
if ( !key )
{
continue;
}
stretch += qskKeyStretch( key );
}
if ( stretch == 0.0 )
{
stretch = ColumnCount;
}
return stretch;
} }
static QString qskTextForKey( int key ) QString QskVirtualKeyboard::textForKey( int key ) const
{ {
// Special cases // Special cases
switch ( key ) switch ( key )
@ -189,191 +212,96 @@ static QString qskTextForKey( int key )
} }
} }
static bool qskIsAutorepeat( int key ) QskVirtualKeyboard::KeyType QskVirtualKeyboard::typeForKey( int key ) const
{ {
return ( switch( key )
( key != Qt::Key_Return ) &&
( key != Qt::Key_Enter ) &&
( key != Qt::Key_Shift ) &&
( key != Qt::Key_CapsLock ) &&
( key != Qt::Key_Mode_switch ) );
}
static QSet< int > qskKeyCodes( const QskVirtualKeyboardLayouts::Layout& layout )
{
QSet< int > codes;
codes.reserve( RowCount * ColumnCount );
for ( int mode = 0; mode <= QskVirtualKeyboard::ModeCount; mode++ )
{ {
const auto& keyCodes = layout[ mode ]; case Qt::Key_Return:
case Qt::Key_Enter:
return EnterType;
for ( int row = 0; row < RowCount; row++ ) case Qt::Key_Backspace:
{ return BackspaceType;
const auto& keys = keyCodes.data[ row ];
for ( int col = 0; col < ColumnCount; col++ ) case Qt::Key_Shift:
codes += keys[ col ]; case Qt::Key_CapsLock:
} return CapsSwitchType;
case Qt::Key_Mode_switch:
return ModeSwitchType;
case Qt::Key_Comma:
case Qt::Key_Period:
return SpecialCharacterType;
default:
return NormalType;
} }
return codes;
} }
QSK_SUBCONTROL( QskVirtualKeyboard, Panel ) void QskVirtualKeyboard::updateLayout() // ### fill keyCodes here
QSK_SUBCONTROL( QskVirtualKeyboard, ButtonPanel )
QSK_SUBCONTROL( QskVirtualKeyboard, ButtonText )
class QskVirtualKeyboard::PrivateData
{
public:
const QskVirtualKeyboardLayouts::Layout* currentLayout = nullptr;
QskVirtualKeyboard::Mode mode = QskVirtualKeyboard::LowercaseMode;
QVector< Button* > keyButtons;
QSet< int > keyCodes;
};
QskVirtualKeyboard::QskVirtualKeyboard( QQuickItem* parent )
: Inherited( parent )
, m_data( new PrivateData )
{
setPolishOnResize( true );
initSizePolicy( QskSizePolicy::Expanding, QskSizePolicy::Fixed );
m_data->keyButtons.reserve( RowCount * ColumnCount );
const auto autoRepeatInterval =
1000 / QGuiApplication::styleHints()->keyboardAutoRepeatRate();
for ( int row = 0; row < RowCount; row++ )
{
for ( int col = 0; col < ColumnCount; col++ )
{
auto button = new Button( row, col, this );
button->installEventFilter( this );
button->setAutoRepeat( false );
button->setAutoRepeatDelay( 500 );
button->setAutoRepeatInterval( autoRepeatInterval );
connect( button, &QskPushButton::pressed,
this, &QskVirtualKeyboard::buttonPressed );
m_data->keyButtons += button;
}
}
connect( this, &QskControl::localeChanged,
this, &QskVirtualKeyboard::updateLocale );
updateLocale( locale() );
}
QskVirtualKeyboard::~QskVirtualKeyboard()
{
}
QskAspect::Subcontrol QskVirtualKeyboard::substitutedSubcontrol(
QskAspect::Subcontrol subControl ) const
{
if ( subControl == QskBox::Panel )
return QskVirtualKeyboard::Panel;
return Inherited::substitutedSubcontrol( subControl );
}
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();
constexpr 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 );
}
void QskVirtualKeyboard::updateLayout()
{ {
const auto r = layoutRect(); const auto r = layoutRect();
if ( r.isEmpty() ) if ( r.isEmpty() )
return; return;
const auto spacing = spacingHint( Panel ); const auto spacing = spacingHint( Panel );
const auto totalVSpacing = ( RowCount - 1 ) * spacing; const auto totalVSpacing = ( rowCount() - 1 ) * spacing;
const auto keyHeight = ( r.height() - totalVSpacing ) / RowCount; const auto keyHeight = ( r.height() - totalVSpacing ) / rowCount();
const auto& keyCodes = ( *m_data->currentLayout )[ m_data->mode ];
qreal yPos = r.top(); qreal yPos = r.top();
for ( int row = 0; row < RowCount; row++ ) const auto& page = ( *m_data->currentLayout )[ mode() ];
{
const auto& keys = keyCodes.data[ row ];
for ( int i = 0; i < page.size(); i++ )
{
const QVector< int > row = page[ i ];
#if 1 #if 1
// there should be a better way // there should be a better way
auto totalHSpacing = -spacing; auto totalHSpacing = -spacing;
if ( spacing ) if ( spacing )
{ {
for ( int col = 0; col < ColumnCount; col++ ) for ( int j = 0; j < row.size(); j++ )
{ {
if ( keys[ col ] != 0 ) if ( row[ j ] != 0 )
totalHSpacing += spacing; totalHSpacing += spacing;
} }
} }
#endif #endif
const auto baseKeyWidth = ( r.width() - totalHSpacing ) / qskRowStretch( keys ); const auto baseKeyWidth = ( r.width() - totalHSpacing ) / rowStretch( row );
qreal xPos = r.left(); qreal xPos = r.left();
for ( int col = 0; col < ColumnCount; col++ ) for ( int j = 0; j < columnCount(); j++ )
{ {
const int key = keys[ col ]; auto button = m_data->keyButtons[ i * columnCount() + j ];
auto button = m_data->keyButtons[ row * ColumnCount + col ];
button->setVisible( key != 0 ); if( j < row.size() )
if ( button->isVisible() )
{ {
const qreal keyWidth = baseKeyWidth * qskKeyStretch( key ); const int key = row[ j ];
button->setVisible( isKeyVisible( key ) );
const QRectF rect( xPos, yPos, keyWidth, keyHeight ); if ( button->isVisible() )
{
const qreal keyWidth = baseKeyWidth * keyStretch( key );
button->setGeometry( rect ); const QRectF rect( xPos, yPos, keyWidth, keyHeight );
button->setAutoRepeat( qskIsAutorepeat( key ) );
button->setText( qskTextForKey( key ) );
xPos += keyWidth + spacing; 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 );
} }
} }
@ -386,14 +314,88 @@ bool QskVirtualKeyboard::hasKey( int keyCode ) const
return m_data->keyCodes.contains( keyCode ); return m_data->keyCodes.contains( keyCode );
} }
int QskVirtualKeyboard::rowCount() const
{
return m_data->rowCount;
}
void QskVirtualKeyboard::setRowCount( int rowCount )
{
m_data->rowCount = rowCount;
ensureButtons();
}
int QskVirtualKeyboard::columnCount() const
{
return m_data->columnCount;
}
void QskVirtualKeyboard::setColumnCount( int columnCount )
{
m_data->columnCount = columnCount;
ensureButtons();
}
QskVirtualKeyboardLayouts QskVirtualKeyboard::layouts() const
{
return m_data->layouts;
}
void QskVirtualKeyboard::setLayouts( const QskVirtualKeyboardLayouts& layouts )
{
m_data->layouts = layouts;
}
void QskVirtualKeyboard::ensureButtons()
{
const int newButtonSize = rowCount() * columnCount();
const int oldButtonSize = m_data->keyButtons.size();
if( newButtonSize == oldButtonSize )
return;
const auto autoRepeatInterval =
1000 / QGuiApplication::styleHints()->keyboardAutoRepeatRate();
m_data->keyButtons.reserve( rowCount() * columnCount() );
for( int i = 0; i < rowCount(); i++ )
{
for( int j = 0; j < columnCount(); j++ )
{
const int index = i * columnCount() + j;
if( index >= m_data->keyButtons.size() )
{
auto button = new Button( this );
button->installEventFilter( this );
button->setAutoRepeat( false );
button->setAutoRepeatDelay( 500 );
button->setAutoRepeatInterval( autoRepeatInterval );
connect( button, &QskPushButton::pressed,
this, &QskVirtualKeyboard::buttonPressed );
m_data->keyButtons += button;
}
}
}
while( m_data->keyButtons.size() > newButtonSize )
{
auto* button = m_data->keyButtons.takeLast();
button->deleteLater();
}
}
void QskVirtualKeyboard::buttonPressed() void QskVirtualKeyboard::buttonPressed()
{ {
const auto button = static_cast< const Button* >( sender() ); const auto button = static_cast< const Button* >( sender() );
if ( button == nullptr ) if ( button == nullptr )
return; return;
const auto& keyCodes = ( *m_data->currentLayout )[ m_data->mode ]; const int key = button->key();
const int key = keyCodes.data[ button->row() ][ button->column() ];
// Mode-switching keys // Mode-switching keys
switch ( key ) switch ( key )
@ -427,6 +429,49 @@ void QskVirtualKeyboard::buttonPressed()
} }
} }
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;
}
void QskVirtualKeyboard::updateLocale( const QLocale& locale ) void QskVirtualKeyboard::updateLocale( const QLocale& locale )
{ {
const QskVirtualKeyboardLayouts::Layout* newLayout = nullptr; const QskVirtualKeyboardLayouts::Layout* newLayout = nullptr;
@ -434,23 +479,23 @@ void QskVirtualKeyboard::updateLocale( const QLocale& locale )
switch ( locale.language() ) switch ( locale.language() )
{ {
case QLocale::Bulgarian: case QLocale::Bulgarian:
newLayout = &qskKeyboardLayouts.bg; newLayout = &m_data->layouts.bg;
break; break;
case QLocale::Czech: case QLocale::Czech:
newLayout = &qskKeyboardLayouts.cs; newLayout = &m_data->layouts.cs;
break; break;
case QLocale::German: case QLocale::German:
newLayout = &qskKeyboardLayouts.de; newLayout = &m_data->layouts.de;
break; break;
case QLocale::Danish: case QLocale::Danish:
newLayout = &qskKeyboardLayouts.da; newLayout = &m_data->layouts.da;
break; break;
case QLocale::Greek: case QLocale::Greek:
newLayout = &qskKeyboardLayouts.el; newLayout = &m_data->layouts.el;
break; break;
case QLocale::English: case QLocale::English:
@ -461,11 +506,11 @@ void QskVirtualKeyboard::updateLocale( const QLocale& locale )
case QLocale::UnitedStates: case QLocale::UnitedStates:
case QLocale::UnitedStatesMinorOutlyingIslands: case QLocale::UnitedStatesMinorOutlyingIslands:
case QLocale::UnitedStatesVirginIslands: case QLocale::UnitedStatesVirginIslands:
newLayout = &qskKeyboardLayouts.en_US; newLayout = &m_data->layouts.en_US;
break; break;
default: default:
newLayout = &qskKeyboardLayouts.en_GB; newLayout = &m_data->layouts.en_GB;
break; break;
} }
@ -473,94 +518,109 @@ void QskVirtualKeyboard::updateLocale( const QLocale& locale )
} }
case QLocale::Spanish: case QLocale::Spanish:
newLayout = &qskKeyboardLayouts.es; newLayout = &m_data->layouts.es;
break; break;
case QLocale::Finnish: case QLocale::Finnish:
newLayout = &qskKeyboardLayouts.fi; newLayout = &m_data->layouts.fi;
break; break;
case QLocale::French: case QLocale::French:
newLayout = &qskKeyboardLayouts.fr; newLayout = &m_data->layouts.fr;
break; break;
case QLocale::Hungarian: case QLocale::Hungarian:
newLayout = &qskKeyboardLayouts.hu; newLayout = &m_data->layouts.hu;
break; break;
case QLocale::Italian: case QLocale::Italian:
newLayout = &qskKeyboardLayouts.it; newLayout = &m_data->layouts.it;
break; break;
case QLocale::Japanese: case QLocale::Japanese:
newLayout = &qskKeyboardLayouts.ja; newLayout = &m_data->layouts.ja;
break; break;
case QLocale::Latvian: case QLocale::Latvian:
newLayout = &qskKeyboardLayouts.lv; newLayout = &m_data->layouts.lv;
break; break;
case QLocale::Lithuanian: case QLocale::Lithuanian:
newLayout = &qskKeyboardLayouts.lt; newLayout = &m_data->layouts.lt;
break; break;
case QLocale::Dutch: case QLocale::Dutch:
newLayout = &qskKeyboardLayouts.nl; newLayout = &m_data->layouts.nl;
break; break;
case QLocale::Portuguese: case QLocale::Portuguese:
newLayout = &qskKeyboardLayouts.pt; newLayout = &m_data->layouts.pt;
break; break;
case QLocale::Romanian: case QLocale::Romanian:
newLayout = &qskKeyboardLayouts.ro; newLayout = &m_data->layouts.ro;
break; break;
case QLocale::Russian: case QLocale::Russian:
newLayout = &qskKeyboardLayouts.ru; newLayout = &m_data->layouts.ru;
break; break;
case QLocale::Slovenian: case QLocale::Slovenian:
newLayout = &qskKeyboardLayouts.sl; newLayout = &m_data->layouts.sl;
break; break;
case QLocale::Slovak: case QLocale::Slovak:
newLayout = &qskKeyboardLayouts.sk; newLayout = &m_data->layouts.sk;
break; break;
case QLocale::Turkish: case QLocale::Turkish:
newLayout = &qskKeyboardLayouts.tr; newLayout = &m_data->layouts.tr;
break; break;
case QLocale::Chinese: case QLocale::Chinese:
newLayout = &qskKeyboardLayouts.zh; newLayout = &m_data->layouts.zh;
break; break;
#if 1 #if 1
case QLocale::C: case QLocale::C:
newLayout = &qskKeyboardLayouts.en_US; newLayout = &m_data->layouts.en_US;
break; break;
#endif #endif
default: default:
qWarning() << "QskVirtualKeyboard: unsupported locale:" << locale; qWarning() << "QskVirtualKeyboard: unsupported locale:" << locale;
newLayout = &qskKeyboardLayouts.en_US; newLayout = &m_data->layouts.en_US;
} }
if ( newLayout != m_data->currentLayout ) if ( newLayout != m_data->currentLayout )
{ {
m_data->currentLayout = newLayout; m_data->currentLayout = newLayout;
m_data->keyCodes = qskKeyCodes( *newLayout ); updateKeyCodes();
setMode( LowercaseMode ); setMode( LowercaseMode );
polish(); polish();
Q_EMIT keyboardLayoutChanged();
} }
} }
void QskVirtualKeyboard::setMode( QskVirtualKeyboard::Mode mode ) QskPushButton::Emphasis QskVirtualKeyboard::emphasisForType( KeyType type )
{ {
m_data->mode = mode; switch( type )
polish(); {
case EnterType:
return QskPushButton::VeryHighEmphasis;
Q_EMIT modeChanged( m_data->mode ); case BackspaceType:
case CapsSwitchType:
return QskPushButton::HighEmphasis;
case ModeSwitchType:
return QskPushButton::LowEmphasis;
case SpecialCharacterType:
return QskPushButton::VeryLowEmphasis;
default:
return QskPushButton::NoEmphasis;
}
} }
#include "moc_QskVirtualKeyboard.cpp" #include "moc_QskVirtualKeyboard.cpp"

View File

@ -7,6 +7,37 @@
#define QSK_VIRTUAL_KEYBOARD_H #define QSK_VIRTUAL_KEYBOARD_H
#include "QskBox.h" #include "QskBox.h"
#include "QskPushButton.h"
class QSK_EXPORT QskVirtualKeyboardLayouts
{
public:
using Layout = QVector< QVector< QVector< int > > >;
Layout bg; // Bulgarian
Layout cs; // Czech
Layout de; // German
Layout da; // Danish
Layout el; // Greek
Layout en_GB; // English (GB)
Layout en_US; // English (US)
Layout es; // Spanish
Layout fi; // Finnish
Layout fr; // French
Layout hu; // Hungarian
Layout it; // Italian
Layout ja; // Japanese
Layout lv; // Latvian
Layout lt; // Lithuanian
Layout nl; // Dutch
Layout pt; // Portuguese
Layout ro; // Romanian
Layout ru; // Russian
Layout sl; // Slovene
Layout sk; // Slovak
Layout tr; // Turkish
Layout zh; // Chinese
};
class QSK_EXPORT QskVirtualKeyboard : public QskBox class QSK_EXPORT QskVirtualKeyboard : public QskBox
{ {
@ -27,6 +58,16 @@ class QSK_EXPORT QskVirtualKeyboard : public QskBox
}; };
Q_ENUM( Mode ) Q_ENUM( Mode )
enum KeyType
{
NormalType,
EnterType,
BackspaceType,
CapsSwitchType,
ModeSwitchType,
SpecialCharacterType
};
QskVirtualKeyboard( QQuickItem* parent = nullptr ); QskVirtualKeyboard( QQuickItem* parent = nullptr );
~QskVirtualKeyboard() override; ~QskVirtualKeyboard() override;
@ -37,19 +78,36 @@ class QSK_EXPORT QskVirtualKeyboard : public QskBox
bool hasKey( int keyCode ) const; bool hasKey( int keyCode ) const;
int rowCount() const;
void setRowCount( int );
int columnCount() const;
void setColumnCount( int );
QskVirtualKeyboardLayouts layouts() const;
void setLayouts( const QskVirtualKeyboardLayouts& );
Q_SIGNALS: Q_SIGNALS:
void modeChanged( Mode ); void modeChanged( QskVirtualKeyboard::Mode );
void keyboardLayoutChanged();
void keySelected( int keyCode ); void keySelected( int keyCode );
protected: protected:
virtual qreal keyStretch( int ) const;
virtual bool isKeyVisible( int ) const;
virtual QString textForKey( int ) const;
virtual KeyType typeForKey( int ) const;
void updateLayout() override; void updateLayout() override;
QSizeF layoutSizeHint( Qt::SizeHint, const QSizeF& ) const override; QSizeF layoutSizeHint( Qt::SizeHint, const QSizeF& ) const override;
QskAspect::Subcontrol substitutedSubcontrol(
QskAspect::Subcontrol ) const override;
private: private:
void ensureButtons();
void buttonPressed(); void buttonPressed();
void updateKeyCodes();
QskPushButton::Emphasis emphasisForType( KeyType );
qreal rowStretch( const QVector< int >& );
class PrivateData; class PrivateData;
std::unique_ptr< PrivateData > m_data; std::unique_ptr< PrivateData > m_data;

File diff suppressed because it is too large Load Diff