input panel improved
This commit is contained in:
parent
7fe675d74d
commit
3ffd9b3a71
@ -18,6 +18,7 @@
|
|||||||
#include <QskTabBar.h>
|
#include <QskTabBar.h>
|
||||||
#include <QskTabView.h>
|
#include <QskTabView.h>
|
||||||
#include <QskInputPanel.h>
|
#include <QskInputPanel.h>
|
||||||
|
#include <QskInputPredictionBar.h>
|
||||||
#include <QskVirtualKeyboard.h>
|
#include <QskVirtualKeyboard.h>
|
||||||
#include <QskScrollView.h>
|
#include <QskScrollView.h>
|
||||||
#include <QskListView.h>
|
#include <QskListView.h>
|
||||||
@ -243,6 +244,7 @@ void QskSquiekSkin::initHints()
|
|||||||
initDialogButtonHints();
|
initDialogButtonHints();
|
||||||
initFocusIndicatorHints();
|
initFocusIndicatorHints();
|
||||||
initInputPanelHints();
|
initInputPanelHints();
|
||||||
|
initInputPredictionBar();
|
||||||
initVirtualKeyboardHints();
|
initVirtualKeyboardHints();
|
||||||
initListViewHints();
|
initListViewHints();
|
||||||
initPageIndicatorHints();
|
initPageIndicatorHints();
|
||||||
@ -622,6 +624,24 @@ void QskSquiekSkin::initInputPanelHints()
|
|||||||
setPanel( Q::Panel, Raised );
|
setPanel( Q::Panel, Raised );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QskSquiekSkin::initInputPredictionBar()
|
||||||
|
{
|
||||||
|
using namespace QskAspect;
|
||||||
|
using Q = QskInputPredictionBar;
|
||||||
|
|
||||||
|
const ColorPalette& pal = m_data->palette;
|
||||||
|
|
||||||
|
setMargins( Q::Panel | Padding, 5 );
|
||||||
|
setPanel( Q::Panel, Flat );
|
||||||
|
|
||||||
|
setButton( Q::ButtonPanel, Flat );
|
||||||
|
setButton( Q::ButtonPanel | QskPushButton::Pressed, Sunken );
|
||||||
|
setMetric( Q::ButtonPanel | MinimumWidth, qskDpiScaled( 30.0 ) );
|
||||||
|
|
||||||
|
setColor( Q::ButtonText, pal.themeForeground );
|
||||||
|
setColor( Q::ButtonText | QskPushButton::Disabled, pal.darker200 );
|
||||||
|
}
|
||||||
|
|
||||||
void QskSquiekSkin::initVirtualKeyboardHints()
|
void QskSquiekSkin::initVirtualKeyboardHints()
|
||||||
{
|
{
|
||||||
using namespace QskAspect;
|
using namespace QskAspect;
|
||||||
|
@ -30,6 +30,7 @@ private:
|
|||||||
void initDialogButtonBoxHints();
|
void initDialogButtonBoxHints();
|
||||||
void initFocusIndicatorHints();
|
void initFocusIndicatorHints();
|
||||||
void initInputPanelHints();
|
void initInputPanelHints();
|
||||||
|
void initInputPredictionBar();
|
||||||
void initVirtualKeyboardHints();
|
void initVirtualKeyboardHints();
|
||||||
void initListViewHints();
|
void initListViewHints();
|
||||||
void initPageIndicatorHints();
|
void initPageIndicatorHints();
|
||||||
|
@ -193,6 +193,50 @@ bool QskInputContext::isAnimating() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QskPopup* QskInputContext::createEmbeddingPopup( QskInputPanel* panel )
|
||||||
|
{
|
||||||
|
auto popup = new QskPopup();
|
||||||
|
|
||||||
|
popup->setAutoLayoutChildren( true );
|
||||||
|
popup->setTransparentForPositioner( false );
|
||||||
|
popup->setModal( true );
|
||||||
|
|
||||||
|
auto box = new QskLinearBox( popup );
|
||||||
|
box->addItem( panel );
|
||||||
|
|
||||||
|
/*
|
||||||
|
When the panel has an input proxy ( usually a local text input )
|
||||||
|
we don't need to see the input item and display the overlay
|
||||||
|
and align in the center of the window.
|
||||||
|
*/
|
||||||
|
const bool hasInputProxy = panel->hasInputProxy();
|
||||||
|
|
||||||
|
popup->setOverlay( hasInputProxy );
|
||||||
|
|
||||||
|
if ( hasInputProxy )
|
||||||
|
box->setMargins( QMarginsF( 5, 5, 5, 5 ) );
|
||||||
|
else
|
||||||
|
box->setExtraSpacingAt( Qt::TopEdge | Qt::LeftEdge | Qt::RightEdge );
|
||||||
|
|
||||||
|
return popup;
|
||||||
|
}
|
||||||
|
|
||||||
|
QskWindow* QskInputContext::createEmbeddingWindow( QskInputPanel* panel )
|
||||||
|
{
|
||||||
|
auto window = new QskWindow();
|
||||||
|
|
||||||
|
window->setFlags( window->flags() & Qt::Dialog );
|
||||||
|
//window->setModality( Qt::ApplicationModal );
|
||||||
|
window->setAutoLayoutChildren( true );
|
||||||
|
#if 0
|
||||||
|
window->setFlags( Qt::Tool | Qt::WindowDoesNotAcceptFocus );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
panel->setParentItem( window->contentItem() );
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
void QskInputContext::showInputPanel()
|
void QskInputContext::showInputPanel()
|
||||||
{
|
{
|
||||||
auto focusItem = qobject_cast< QQuickItem* >( qGuiApp->focusObject() );
|
auto focusItem = qobject_cast< QQuickItem* >( qGuiApp->focusObject() );
|
||||||
@ -209,9 +253,6 @@ void QskInputContext::showInputPanel()
|
|||||||
|
|
||||||
m_data->inputItem = focusItem;
|
m_data->inputItem = focusItem;
|
||||||
|
|
||||||
auto& inputPopup = m_data->inputPopup;
|
|
||||||
auto& inputWindow = m_data->inputWindow;
|
|
||||||
|
|
||||||
if ( qskInputPanel == nullptr )
|
if ( qskInputPanel == nullptr )
|
||||||
qskSetInputPanel( new QskInputPanel() );
|
qskSetInputPanel( new QskInputPanel() );
|
||||||
|
|
||||||
@ -227,66 +268,53 @@ void QskInputContext::showInputPanel()
|
|||||||
{
|
{
|
||||||
// The input panel is embedded in a top level window
|
// The input panel is embedded in a top level window
|
||||||
|
|
||||||
delete inputPopup;
|
delete m_data->inputPopup;
|
||||||
|
|
||||||
if ( inputWindow == nullptr )
|
if ( m_data->inputWindow == nullptr )
|
||||||
{
|
{
|
||||||
inputWindow = new QskWindow();
|
auto window = createEmbeddingWindow( qskInputPanel );
|
||||||
inputWindow->setDeleteOnClose( true );
|
|
||||||
#if 0
|
|
||||||
inputWindow->setFlags( Qt::Tool | Qt::WindowDoesNotAcceptFocus );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
qskInputPanel->setParentItem( inputWindow->contentItem() );
|
if ( window )
|
||||||
|
{
|
||||||
|
QSize size = window->effectivePreferredSize();
|
||||||
|
if ( size.isEmpty() )
|
||||||
|
{
|
||||||
|
// no idea, may be something based on the screen size
|
||||||
|
size = QSize( 800, 240 );
|
||||||
|
}
|
||||||
|
|
||||||
|
window->resize( size );
|
||||||
|
window->show();
|
||||||
|
|
||||||
|
window->setDeleteOnClose( true );
|
||||||
|
window->installEventFilter( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_data->inputWindow = window;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize size = qskInputPanel->sizeHint().toSize();
|
|
||||||
if ( size.isEmpty() )
|
|
||||||
{
|
|
||||||
// no idea, may be something based on the screen size
|
|
||||||
size = QSize( 800, 240 );
|
|
||||||
}
|
|
||||||
|
|
||||||
inputWindow->resize( size );
|
|
||||||
inputWindow->show();
|
|
||||||
|
|
||||||
inputWindow->installEventFilter( this );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// The input panel is embedded in a popup
|
// The input panel is embedded in a popup
|
||||||
|
|
||||||
delete inputWindow;
|
delete m_data->inputWindow;
|
||||||
|
|
||||||
if ( inputPopup == nullptr )
|
if ( m_data->inputPopup == nullptr )
|
||||||
{
|
{
|
||||||
inputPopup = new QskPopup( m_data->inputItem->window()->contentItem() );
|
auto popup = createEmbeddingPopup( qskInputPanel );
|
||||||
|
|
||||||
inputPopup->setAutoLayoutChildren( true );
|
if ( popup )
|
||||||
inputPopup->setTransparentForPositioner( false );
|
{
|
||||||
inputPopup->setModal( true );
|
popup->setParentItem( m_data->inputItem->window()->contentItem() );
|
||||||
|
if ( popup->parent() == nullptr )
|
||||||
|
popup->setParent( this );
|
||||||
|
|
||||||
auto box = new QskLinearBox( inputPopup );
|
popup->setVisible( true );
|
||||||
box->addItem( qskInputPanel );
|
popup->installEventFilter( this );
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
m_data->inputPopup = popup;
|
||||||
When the panel has an input proxy ( usually a local text input )
|
|
||||||
we don't need to see the input item and display the overlay
|
|
||||||
and align in the center of the window.
|
|
||||||
*/
|
|
||||||
const bool hasInputProxy = qskInputPanel->hasInputProxy();
|
|
||||||
|
|
||||||
inputPopup->setOverlay( hasInputProxy );
|
|
||||||
|
|
||||||
if ( hasInputProxy )
|
|
||||||
box->setMargins( QMarginsF( 5, 5, 5, 5 ) );
|
|
||||||
else
|
|
||||||
box->setExtraSpacingAt( Qt::TopEdge | Qt::LeftEdge | Qt::RightEdge );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inputPopup->setParentItem( m_data->inputItem->window()->contentItem() );
|
|
||||||
inputPopup->setVisible( true );
|
|
||||||
inputPopup->installEventFilter( this );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_data->engine->setPredictor(
|
m_data->engine->setPredictor(
|
||||||
@ -314,7 +342,17 @@ void QskInputContext::hideInputPanel()
|
|||||||
focusItem->setFocus( false );
|
focusItem->setFocus( false );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( qskInputPanel )
|
||||||
|
{
|
||||||
|
qskInputPanel->setParentItem( nullptr );
|
||||||
|
qskInputPanel->attachInputItem( nullptr );
|
||||||
|
qskInputPanel->setEngine( nullptr );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( m_data->inputPopup )
|
||||||
|
{
|
||||||
m_data->inputPopup->deleteLater();
|
m_data->inputPopup->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,14 +365,6 @@ void QskInputContext::hideInputPanel()
|
|||||||
window->close(); // deleteOnClose is set
|
window->close(); // deleteOnClose is set
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( qskInputPanel )
|
|
||||||
{
|
|
||||||
//qskInputPanel->setVisible( false );
|
|
||||||
qskInputPanel->setParentItem( nullptr );
|
|
||||||
qskInputPanel->attachInputItem( nullptr );
|
|
||||||
qskInputPanel->setEngine( nullptr );
|
|
||||||
}
|
|
||||||
|
|
||||||
m_data->inputItem = nullptr;
|
m_data->inputItem = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,47 +400,46 @@ void QskInputContext::setFocusObject( QObject* focusObject )
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool doTerminate = true;
|
const auto w = m_data->inputItem->window();
|
||||||
|
if ( w == nullptr )
|
||||||
|
return;
|
||||||
|
|
||||||
if ( focusObject == nullptr && m_data->inputPopup )
|
if ( m_data->inputWindow )
|
||||||
{
|
{
|
||||||
if ( const auto window = m_data->inputItem->window() )
|
if ( focusObject == nullptr )
|
||||||
{
|
{
|
||||||
auto focusItem = window->contentItem()->scopedFocusItem();
|
if ( m_data->inputItem->hasFocus() )
|
||||||
if ( focusItem == m_data->inputPopup )
|
|
||||||
doTerminate = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( doTerminate )
|
|
||||||
{
|
|
||||||
if ( m_data->inputWindow )
|
|
||||||
{
|
|
||||||
auto focusWindow = QGuiApplication::focusWindow();
|
|
||||||
|
|
||||||
if ( focusWindow == nullptr ||
|
|
||||||
QGuiApplication::focusWindow() == m_data->inputWindow )
|
|
||||||
{
|
{
|
||||||
doTerminate = false;
|
/*
|
||||||
|
As long as the focus is noewhere and
|
||||||
|
the local focus stay on the input item
|
||||||
|
we don't care
|
||||||
|
*/
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( m_data->inputPopup )
|
else
|
||||||
{
|
{
|
||||||
auto focusItem = qobject_cast< QQuickItem* >( focusObject );
|
const auto focusItem = qobject_cast< QQuickItem* >( focusObject );
|
||||||
|
if ( focusItem && focusItem->window() == m_data->inputWindow )
|
||||||
if ( ( focusItem == m_data->inputPopup )
|
return;
|
||||||
|| qskIsAncestorOf( m_data->inputPopup, focusItem ) )
|
}
|
||||||
{
|
}
|
||||||
doTerminate = false;
|
else if ( m_data->inputPopup )
|
||||||
}
|
{
|
||||||
|
if ( w->contentItem()->scopedFocusItem() == m_data->inputPopup )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
As long as the focus stays inside the inputPopup
|
||||||
|
we don't care
|
||||||
|
*/
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( doTerminate )
|
hideInputPanel();
|
||||||
{
|
m_data->inputItem = nullptr;
|
||||||
hideInputPanel();
|
|
||||||
m_data->inputItem = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskInputContext::registerPredictor(
|
void QskInputContext::registerPredictor(
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
|
|
||||||
class QskTextPredictor;
|
class QskTextPredictor;
|
||||||
class QskInputPanel;
|
class QskInputPanel;
|
||||||
|
class QskPopup;
|
||||||
|
class QskWindow;
|
||||||
class QQuickItem;
|
class QQuickItem;
|
||||||
|
|
||||||
class QSK_EXPORT QskInputContext : public QPlatformInputContext
|
class QSK_EXPORT QskInputContext : public QPlatformInputContext
|
||||||
@ -58,6 +60,9 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual bool eventFilter( QObject*, QEvent* ) override;
|
virtual bool eventFilter( QObject*, QEvent* ) override;
|
||||||
|
|
||||||
|
virtual QskPopup* createEmbeddingPopup( QskInputPanel* );
|
||||||
|
virtual QskWindow* createEmbeddingWindow( QskInputPanel* );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class PrivateData;
|
class PrivateData;
|
||||||
std::unique_ptr< PrivateData > m_data;
|
std::unique_ptr< PrivateData > m_data;
|
||||||
|
@ -240,8 +240,11 @@ QskInputEngine::Result QskInputEngine::processKey( int key,
|
|||||||
|
|
||||||
QString QskInputEngine::predictiveText( int index ) const
|
QString QskInputEngine::predictiveText( int index ) const
|
||||||
{
|
{
|
||||||
if ( m_data->predictor )
|
if ( const QskTextPredictor* predictor = m_data->predictor )
|
||||||
return m_data->predictor->candidate( index );
|
{
|
||||||
|
if ( index >= 0 && index < predictor->candidateCount() )
|
||||||
|
return predictor->candidate( index );
|
||||||
|
}
|
||||||
|
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
@ -110,14 +110,16 @@ static inline void qskSyncInputProxy(
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
class TextInput final : public QskTextInput
|
class TextInputProxy final : public QskTextInput
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TextInput( QQuickItem* parentItem = nullptr ):
|
TextInputProxy( QQuickItem* parentItem = nullptr ):
|
||||||
QskTextInput( parentItem )
|
QskTextInput( parentItem )
|
||||||
{
|
{
|
||||||
setObjectName( "InputPanelInputProxy" );
|
setObjectName( "InputPanelInputProxy" );
|
||||||
|
#if 1
|
||||||
setFocusPolicy( Qt::NoFocus );
|
setFocusPolicy( Qt::NoFocus );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -154,7 +156,7 @@ public:
|
|||||||
|
|
||||||
QskLinearBox* layout;
|
QskLinearBox* layout;
|
||||||
QskTextLabel* prompt;
|
QskTextLabel* prompt;
|
||||||
TextInput* inputProxy;
|
TextInputProxy* inputProxy;
|
||||||
QskInputPredictionBar* predictionBar;
|
QskInputPredictionBar* predictionBar;
|
||||||
QskVirtualKeyboard* keyboard;
|
QskVirtualKeyboard* keyboard;
|
||||||
|
|
||||||
@ -175,7 +177,7 @@ QskInputPanel::QskInputPanel( QQuickItem* parent ):
|
|||||||
m_data->prompt = new QskTextLabel();
|
m_data->prompt = new QskTextLabel();
|
||||||
m_data->prompt->setVisible( false );
|
m_data->prompt->setVisible( false );
|
||||||
|
|
||||||
m_data->inputProxy = new TextInput();
|
m_data->inputProxy = new TextInputProxy();
|
||||||
m_data->inputProxy->setVisible( m_data->hasInputProxy );
|
m_data->inputProxy->setVisible( m_data->hasInputProxy );
|
||||||
|
|
||||||
m_data->predictionBar = new QskInputPredictionBar();
|
m_data->predictionBar = new QskInputPredictionBar();
|
||||||
@ -331,9 +333,11 @@ void QskInputPanel::commitPredictiveText( int index )
|
|||||||
if ( m_data->engine )
|
if ( m_data->engine )
|
||||||
{
|
{
|
||||||
const QString text = m_data->engine->predictiveText( index );
|
const QString text = m_data->engine->predictiveText( index );
|
||||||
m_data->engine->reset();
|
|
||||||
|
|
||||||
qskSendText( m_data->inputItem, text, true );
|
m_data->engine->reset();
|
||||||
|
m_data->predictionBar->setPrediction( QVector< QString >() );
|
||||||
|
|
||||||
|
qskSendText( m_data->receiverItem(), text, true );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -599,6 +603,18 @@ void QskInputPanel::keyPressEvent( QKeyEvent* event )
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Qt::Key_Shift:
|
||||||
|
case Qt::Key_Control:
|
||||||
|
case Qt::Key_Meta:
|
||||||
|
case Qt::Key_Alt:
|
||||||
|
case Qt::Key_AltGr:
|
||||||
|
case Qt::Key_CapsLock:
|
||||||
|
case Qt::Key_NumLock:
|
||||||
|
case Qt::Key_ScrollLock:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
const auto text = event->text();
|
const auto text = event->text();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user