QskInputContext improvements
This commit is contained in:
parent
07d5d933c1
commit
0ee83c1e32
@ -11,9 +11,11 @@
|
||||
|
||||
#include "QskInputPanel.h"
|
||||
#include <QskDialog.h>
|
||||
#include <QskPopup.h>
|
||||
#include <QskWindow.h>
|
||||
#include <QskControl.h>
|
||||
#include <QskSetup.h>
|
||||
#include <QskEvent.h>
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QHash>
|
||||
@ -82,14 +84,16 @@ static void qskSetCandidates( QQuickItem* inputPanel,
|
||||
class QskInputContext::PrivateData
|
||||
{
|
||||
public:
|
||||
PrivateData():
|
||||
ownsInputPanelWindow( false )
|
||||
{
|
||||
}
|
||||
|
||||
// item receiving the input
|
||||
QPointer< QQuickItem > inputItem;
|
||||
|
||||
// item, wher the user enters texts/keys
|
||||
QPointer< QQuickItem > inputPanel;
|
||||
|
||||
// popup or window embedding the inputPanel
|
||||
QPointer< QskPopup > inputPopup;
|
||||
QPointer< QskWindow > inputWindow;
|
||||
|
||||
QskInputCompositionModel* compositionModel;
|
||||
QHash< QLocale, QskInputCompositionModel* > compositionModels;
|
||||
|
||||
@ -123,10 +127,6 @@ QskInputContext::QskInputContext():
|
||||
|
||||
QskInputContext::~QskInputContext()
|
||||
{
|
||||
#if 1
|
||||
if ( m_data->inputPanel )
|
||||
delete m_data->inputPanel;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool QskInputContext::isValid() const
|
||||
@ -152,13 +152,10 @@ void QskInputContext::setInputItem( QQuickItem* item )
|
||||
|
||||
m_data->inputItem = item;
|
||||
|
||||
if ( m_data->inputItem == nullptr )
|
||||
{
|
||||
hideInputPanel();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( item )
|
||||
update( Qt::ImQueryAll );
|
||||
else
|
||||
hideInputPanel();
|
||||
}
|
||||
|
||||
void QskInputContext::update( Qt::InputMethodQueries queries )
|
||||
@ -271,57 +268,123 @@ bool QskInputContext::isAnimating() const
|
||||
|
||||
void QskInputContext::showInputPanel()
|
||||
{
|
||||
if ( !m_data->inputPanel )
|
||||
auto& inputPanel = m_data->inputPanel;
|
||||
auto& inputPopup = m_data->inputPopup;
|
||||
auto& inputWindow = m_data->inputWindow;
|
||||
|
||||
if ( inputPanel == nullptr )
|
||||
{
|
||||
setInputPanel( new QskInputPanel() );
|
||||
auto panel = new QskInputPanel();
|
||||
panel->setParent( this );
|
||||
|
||||
if ( QskDialog::instance()->policy() == QskDialog::TopLevelWindow )
|
||||
setInputPanel( panel );
|
||||
}
|
||||
|
||||
const bool isPopupPanel = qobject_cast< QskPopup* >( inputPanel );
|
||||
|
||||
bool useWindow = false;
|
||||
if ( !isPopupPanel )
|
||||
{
|
||||
m_data->ownsInputPanelWindow = true;
|
||||
useWindow = ( QskDialog::instance()->policy() == QskDialog::TopLevelWindow );
|
||||
}
|
||||
|
||||
auto window = new QskWindow;
|
||||
window->setFlags( Qt::Tool | Qt::WindowDoesNotAcceptFocus );
|
||||
window->resize( 800, 240 ); // ### what size?
|
||||
if ( useWindow )
|
||||
{
|
||||
delete inputPopup;
|
||||
|
||||
m_data->inputPanel->setParentItem( window->contentItem() );
|
||||
connect( window, &QskWindow::visibleChanged,
|
||||
this, &QskInputContext::emitInputPanelVisibleChanged );
|
||||
if ( inputWindow == nullptr )
|
||||
{
|
||||
inputWindow = new QskWindow();
|
||||
inputWindow->setDeleteOnClose( true );
|
||||
inputWindow->setFlags( Qt::Tool | Qt::WindowDoesNotAcceptFocus );
|
||||
|
||||
inputPanel->setParentItem( inputWindow->contentItem() );
|
||||
|
||||
inputWindow->resize( 800, 240 ); // ### what size?
|
||||
inputWindow->show();
|
||||
|
||||
inputWindow->installEventFilter( this );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto window = qobject_cast< QQuickWindow* >( QGuiApplication::focusWindow() );
|
||||
delete inputWindow;
|
||||
|
||||
if ( inputPopup == nullptr )
|
||||
{
|
||||
if ( isPopupPanel )
|
||||
{
|
||||
inputPopup = qobject_cast< QskPopup* >( inputPanel );
|
||||
}
|
||||
else
|
||||
{
|
||||
auto popup = new QskPopup( m_data->inputItem->window()->contentItem() );
|
||||
popup->setAutoLayoutChildren( true );
|
||||
popup->setModal( true );
|
||||
|
||||
inputPanel->setParentItem( popup );
|
||||
inputPopup = popup;
|
||||
}
|
||||
|
||||
inputPopup->installEventFilter( this );
|
||||
}
|
||||
|
||||
if ( inputPopup->window() == nullptr )
|
||||
{
|
||||
QQuickWindow* window = nullptr;
|
||||
if ( m_data->inputItem )
|
||||
window = m_data->inputItem->window();
|
||||
else
|
||||
window = qobject_cast< QQuickWindow* >( QGuiApplication::focusWindow() );
|
||||
|
||||
if ( window )
|
||||
{
|
||||
m_data->inputPanel->setParentItem( window->contentItem() );
|
||||
m_data->inputPanel->setSize( window->size() );
|
||||
}
|
||||
inputPopup->setParentItem( window->contentItem() );
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_data->ownsInputPanelWindow )
|
||||
{
|
||||
if ( m_data->inputPanel->window() )
|
||||
m_data->inputPanel->window()->show();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_data->inputPanel->setVisible( true );
|
||||
inputPopup->setGeometry( qskItemGeometry( inputPopup->parentItem() ) );
|
||||
inputPopup->setVisible( true );
|
||||
}
|
||||
|
||||
inputPanel->setVisible( true );
|
||||
|
||||
connect( inputPanel->window(), &QskWindow::visibleChanged,
|
||||
this, &QskInputContext::emitInputPanelVisibleChanged );
|
||||
}
|
||||
|
||||
void QskInputContext::hideInputPanel()
|
||||
{
|
||||
if ( m_data->inputPanel == nullptr )
|
||||
return;
|
||||
|
||||
if ( m_data->ownsInputPanelWindow )
|
||||
if ( m_data->inputPanel )
|
||||
{
|
||||
if ( auto window = m_data->inputPanel->window() )
|
||||
window->hide();
|
||||
// to get rid of the scene graph nodes
|
||||
m_data->inputPanel->setVisible( false );
|
||||
}
|
||||
|
||||
if ( m_data->inputPopup == m_data->inputPanel )
|
||||
{
|
||||
|
||||
m_data->inputPopup->removeEventFilter( this );
|
||||
m_data->inputPopup = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_data->inputPanel->setVisible( false );
|
||||
if ( m_data->inputPopup )
|
||||
{
|
||||
auto popup = m_data->inputPopup.data();
|
||||
m_data->inputPopup = nullptr;
|
||||
|
||||
popup->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
QskWindow* window = m_data->inputWindow;
|
||||
m_data->inputWindow = nullptr;
|
||||
|
||||
if ( window )
|
||||
{
|
||||
window->removeEventFilter( this );
|
||||
window->close(); // deleteOnClose is set
|
||||
}
|
||||
|
||||
qGuiApp->removeEventFilter( this );
|
||||
@ -361,10 +424,29 @@ void QskInputContext::setFocusObject( QObject* focusObject )
|
||||
{
|
||||
/*
|
||||
Do not change the input item when
|
||||
navigating on or into the panel
|
||||
navigating to or inside the input popup/window
|
||||
*/
|
||||
|
||||
if( qskNearestFocusScope( focusItem ) != m_data->inputPanel )
|
||||
bool isAccepted = ( m_data->inputItem == nullptr );
|
||||
|
||||
if ( !isAccepted )
|
||||
{
|
||||
if ( m_data->inputWindow )
|
||||
{
|
||||
if ( focusItem->window() != m_data->inputWindow )
|
||||
isAccepted = true;
|
||||
}
|
||||
else if ( m_data->inputPopup )
|
||||
{
|
||||
if ( ( focusItem != m_data->inputPopup )
|
||||
&& !qskIsAncestorOf( m_data->inputPopup, focusItem ) )
|
||||
{
|
||||
isAccepted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( isAccepted )
|
||||
setInputItem( focusItem );
|
||||
}
|
||||
|
||||
@ -469,6 +551,15 @@ void QskInputContext::setInputPanel( QQuickItem* inputPanel )
|
||||
{
|
||||
m_data->inputPanel->disconnect( this );
|
||||
|
||||
if ( m_data->inputPanel->parent() == this )
|
||||
{
|
||||
delete m_data->inputPanel;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_data->inputPanel->setParentItem( nullptr );
|
||||
}
|
||||
|
||||
if ( model )
|
||||
model->disconnect( m_data->inputPanel );
|
||||
}
|
||||
@ -478,25 +569,12 @@ void QskInputContext::setInputPanel( QQuickItem* inputPanel )
|
||||
|
||||
if ( inputPanel )
|
||||
{
|
||||
if ( inputPanel->parent() == nullptr )
|
||||
inputPanel->setParent( this );
|
||||
|
||||
connect( inputPanel, &QQuickItem::visibleChanged,
|
||||
this, &QPlatformInputContext::emitInputPanelVisibleChanged );
|
||||
|
||||
// maybe using a QQuickItemChangeListener instead
|
||||
#if 1
|
||||
|
||||
connect( inputPanel, &QQuickItem::xChanged,
|
||||
this, &QPlatformInputContext::emitKeyboardRectChanged );
|
||||
|
||||
connect( inputPanel, &QQuickItem::yChanged,
|
||||
this, &QPlatformInputContext::emitKeyboardRectChanged );
|
||||
|
||||
connect( inputPanel, &QQuickItem::widthChanged,
|
||||
this, &QPlatformInputContext::emitKeyboardRectChanged );
|
||||
|
||||
connect( inputPanel, &QQuickItem::heightChanged,
|
||||
this, &QPlatformInputContext::emitKeyboardRectChanged );
|
||||
#endif
|
||||
|
||||
if ( auto control = qobject_cast< QskControl* >( inputPanel ) )
|
||||
{
|
||||
connect( control, &QskControl::localeChanged,
|
||||
@ -521,7 +599,24 @@ void QskInputContext::commit()
|
||||
|
||||
bool QskInputContext::eventFilter( QObject* object, QEvent* event )
|
||||
{
|
||||
if ( event->type() == QEvent::InputMethodQuery )
|
||||
switch( static_cast< int >( event->type() ) )
|
||||
{
|
||||
case QEvent::Move:
|
||||
case QEvent::Resize:
|
||||
{
|
||||
if ( m_data->inputPanel && object == m_data->inputPanel->window() )
|
||||
emitKeyboardRectChanged();
|
||||
|
||||
break;
|
||||
}
|
||||
case QskEvent::GeometryChange:
|
||||
{
|
||||
if ( object == m_data->inputPopup )
|
||||
emitKeyboardRectChanged();
|
||||
|
||||
break;
|
||||
}
|
||||
case QEvent::InputMethodQuery:
|
||||
{
|
||||
/*
|
||||
Qt/Quick expects that the item associated with the input context
|
||||
@ -536,6 +631,9 @@ bool QskInputContext::eventFilter( QObject* object, QEvent* event )
|
||||
sendEventToInputItem( event );
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Inherited::eventFilter( object, event );
|
||||
|
@ -26,35 +26,26 @@
|
||||
#define STRINGIFY(x) #x
|
||||
#define STRING(x) STRINGIFY(x)
|
||||
|
||||
#define LOCAL_PANEL 1
|
||||
|
||||
class InputBox : public QskLinearBox
|
||||
{
|
||||
public:
|
||||
InputBox( QQuickItem* parentItem = nullptr ):
|
||||
QskLinearBox( Qt::Vertical, parentItem )
|
||||
{
|
||||
setDefaultAlignment( Qt::AlignHCenter | Qt::AlignTop );
|
||||
setExtraSpacingAt( Qt::BottomEdge | Qt::RightEdge );
|
||||
|
||||
setMargins( 10 );
|
||||
setSpacing( 10 );
|
||||
|
||||
auto* textInput = new QskTextInput( this );
|
||||
textInput->setText( "I am a line edit. Press and edit Me." );
|
||||
textInput->setSelectByMouse( true );
|
||||
textInput->setSizePolicy( Qt::Horizontal, QskSizePolicy::Preferred );
|
||||
auto* textInput1 = new QskTextInput( this );
|
||||
textInput1->setText( "I am a line edit. Press and edit Me." );
|
||||
textInput1->setSelectByMouse( true );
|
||||
textInput1->setSizePolicy( Qt::Horizontal, QskSizePolicy::Preferred );
|
||||
|
||||
#if LOCAL_PANEL
|
||||
auto* inputPanel = new QskInputPanel( this );
|
||||
inputPanel->setVisible( false );
|
||||
|
||||
/*
|
||||
QskInputContext is connected to QskSetup::inputPanelChanged,
|
||||
making it the system input. If no input panel has been assigned
|
||||
QskInputContext would create a window or subwindow on the fly.
|
||||
*/
|
||||
qskSetup->setInputPanel( inputPanel );
|
||||
#endif
|
||||
auto* textInput2 = new QskTextInput( this );
|
||||
textInput2->setText( "Another text" );
|
||||
textInput2->setSelectByMouse( true );
|
||||
textInput2->setSizePolicy( Qt::Horizontal, QskSizePolicy::Preferred );
|
||||
}
|
||||
};
|
||||
|
||||
@ -169,11 +160,20 @@ int main( int argc, char* argv[] )
|
||||
SkinnyFont::init( &app );
|
||||
SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts );
|
||||
|
||||
#if !LOCAL_PANEL
|
||||
#if 0
|
||||
// We don't want to have a top level window.
|
||||
qskDialog->setPolicy( QskDialog::EmbeddedBox );
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/*
|
||||
QskInputContext is connected to QskSetup::inputPanelChanged,
|
||||
making it the system input. If no input panel has been assigned
|
||||
QskInputContext would create a window or subwindow on the fly.
|
||||
*/
|
||||
qskSetup->setInputPanel( new QskInputPanel() );
|
||||
#endif
|
||||
|
||||
auto box = new QskLinearBox( Qt::Horizontal );
|
||||
box->setSpacing( 10 );
|
||||
box->setMargins( 20 );
|
||||
|
@ -1538,10 +1538,13 @@ void QskControl::cleanupNodes()
|
||||
d->dirtyAttributes |= QQuickItemPrivate::EffectReference;
|
||||
}
|
||||
|
||||
if ( d->window )
|
||||
{
|
||||
// putting the nodes on the cleanup list of the window to be deleteted
|
||||
// in the next cycle of the scene graph
|
||||
|
||||
QQuickWindowPrivate::get( window() )->cleanup( d->itemNodeInstance );
|
||||
QQuickWindowPrivate::get( d->window )->cleanup( d->itemNodeInstance );
|
||||
}
|
||||
|
||||
// now we can forget about the nodes
|
||||
|
||||
|
@ -111,11 +111,6 @@ QskInputPanel::QskInputPanel( QQuickItem* parent ):
|
||||
m_data( new PrivateData() )
|
||||
{
|
||||
setAutoLayoutChildren( true );
|
||||
setFlag( ItemIsFocusScope, true );
|
||||
#if 0
|
||||
// TODO ...
|
||||
setTabFence( true );
|
||||
#endif
|
||||
|
||||
auto layout = new QskLinearBox( Qt::Vertical, this );
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user