QskInputGrabber added
This commit is contained in:
parent
7ee3ff436d
commit
73d911cee2
|
@ -0,0 +1,218 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "QskInputGrabber.h"
|
||||||
|
#include "QskWindow.h"
|
||||||
|
#include "QskQuick.h"
|
||||||
|
#include <QPointer>
|
||||||
|
|
||||||
|
QSK_QT_PRIVATE_BEGIN
|
||||||
|
#include <private/qquickitem_p.h>
|
||||||
|
#include <private/qquickitemchangelistener_p.h>
|
||||||
|
QSK_QT_PRIVATE_END
|
||||||
|
|
||||||
|
class QskInputGrabber::PrivateData : public QQuickItemChangeListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PrivateData( QskInputGrabber* grabber ):
|
||||||
|
m_grabber( grabber )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QRectF grabberRect() const
|
||||||
|
{
|
||||||
|
if ( itemBelow && itemAbove )
|
||||||
|
{
|
||||||
|
const auto pos = itemBelow->mapToItem( itemAbove, QPointF() );
|
||||||
|
return QRectF( pos.x(), pos.y(), itemBelow->width(), itemBelow->height() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return QRectF();
|
||||||
|
}
|
||||||
|
|
||||||
|
void enableListener( QQuickItem* item,
|
||||||
|
QQuickItemPrivate::ChangeTypes types, bool on )
|
||||||
|
{
|
||||||
|
if ( item )
|
||||||
|
{
|
||||||
|
auto d = QQuickItemPrivate::get( item );
|
||||||
|
|
||||||
|
if ( on )
|
||||||
|
d->addItemChangeListener( this, types );
|
||||||
|
else
|
||||||
|
d->removeItemChangeListener( this, types );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup( QQuickItem* item )
|
||||||
|
{
|
||||||
|
QQuickItem* newItemBelow = item ? item->parentItem() : nullptr;
|
||||||
|
QQuickItem* newItemAbove = item;
|
||||||
|
|
||||||
|
if ( newItemBelow != itemBelow )
|
||||||
|
{
|
||||||
|
const auto changeTypes = QQuickItemPrivate::Geometry;
|
||||||
|
|
||||||
|
enableListener( itemBelow, changeTypes, false );
|
||||||
|
enableListener( newItemBelow, changeTypes, true );
|
||||||
|
|
||||||
|
itemBelow = newItemBelow;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( newItemAbove != itemAbove )
|
||||||
|
{
|
||||||
|
const auto changeTypes = QQuickItemPrivate::Geometry | QQuickItemPrivate::Parent;
|
||||||
|
|
||||||
|
enableListener( itemAbove, changeTypes, false );
|
||||||
|
enableListener( newItemAbove, changeTypes, true );
|
||||||
|
|
||||||
|
itemAbove = newItemAbove;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
|
||||||
|
virtual void itemGeometryChanged( QQuickItem* item,
|
||||||
|
QQuickGeometryChange change, const QRectF& ) override final
|
||||||
|
{
|
||||||
|
bool doUpdate = false;
|
||||||
|
|
||||||
|
if ( item == itemAbove )
|
||||||
|
doUpdate = change.positionChange();
|
||||||
|
else
|
||||||
|
doUpdate = change.sizeChange();
|
||||||
|
|
||||||
|
if ( doUpdate )
|
||||||
|
m_grabber->updateGeometry();
|
||||||
|
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
virtual void itemGeometryChanged(
|
||||||
|
QQuickItem* item, const QRectF& newRect, const QRectF& oldRect ) override
|
||||||
|
{
|
||||||
|
bool doUpdate = false;
|
||||||
|
|
||||||
|
if ( item == itemAbove )
|
||||||
|
doUpdate = newRect.size() != oldRect.size();
|
||||||
|
else
|
||||||
|
doUpdate = newRect.topLeft() != oldRect.topLeft();
|
||||||
|
|
||||||
|
if ( doUpdate )
|
||||||
|
m_grabber->updateGeometry();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
virtual void itemParentChanged( QQuickItem* item, QQuickItem* parentItem ) override
|
||||||
|
{
|
||||||
|
if ( item == m_grabber && parentItem )
|
||||||
|
{
|
||||||
|
setup( parentItem );
|
||||||
|
m_grabber->updateGeometry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QskInputGrabber* m_grabber;
|
||||||
|
|
||||||
|
public:
|
||||||
|
QPointer< QQuickItem > itemAbove;
|
||||||
|
QPointer< QQuickItem > itemBelow;
|
||||||
|
};
|
||||||
|
|
||||||
|
QskInputGrabber::QskInputGrabber( QQuickItem* parent ) :
|
||||||
|
Inherited( parent ),
|
||||||
|
m_data( new PrivateData( this ) )
|
||||||
|
{
|
||||||
|
setAcceptedMouseButtons( Qt::AllButtons );
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
|
||||||
|
setAcceptTouchEvents( true );
|
||||||
|
#endif
|
||||||
|
setAcceptHoverEvents( true );
|
||||||
|
|
||||||
|
setTransparentForPositioner( true );
|
||||||
|
setFlag( QQuickItem::ItemHasContents, false );
|
||||||
|
|
||||||
|
m_data->setup( parent );
|
||||||
|
updateGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
|
QskInputGrabber::~QskInputGrabber()
|
||||||
|
{
|
||||||
|
m_data->setup( nullptr );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QskInputGrabber::event( QEvent* event )
|
||||||
|
{
|
||||||
|
bool doBlock = false;
|
||||||
|
|
||||||
|
switch ( static_cast< int >( event->type() ) )
|
||||||
|
{
|
||||||
|
case QEvent::MouseButtonPress:
|
||||||
|
case QEvent::MouseMove:
|
||||||
|
case QEvent::MouseButtonRelease:
|
||||||
|
{
|
||||||
|
const auto ev = static_cast< QMouseEvent* > ( event );
|
||||||
|
doBlock = isBlocking( ev->localPos() );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QEvent::TouchBegin:
|
||||||
|
case QEvent::TouchUpdate:
|
||||||
|
case QEvent::TouchCancel:
|
||||||
|
{
|
||||||
|
#if 1
|
||||||
|
// TODO
|
||||||
|
doBlock = true;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QEvent::Wheel:
|
||||||
|
{
|
||||||
|
const auto ev = static_cast< QWheelEvent* > ( event );
|
||||||
|
doBlock = isBlocking( ev->posF() );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QEvent::HoverEnter:
|
||||||
|
case QEvent::HoverLeave:
|
||||||
|
{
|
||||||
|
const auto ev = static_cast< QHoverEvent* > ( event );
|
||||||
|
doBlock = isBlocking( ev->posF() );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( doBlock )
|
||||||
|
{
|
||||||
|
event->accept();
|
||||||
|
|
||||||
|
if ( auto w = qobject_cast< QskWindow* >( window() ) )
|
||||||
|
w->setEventAcceptance( QskWindow::EventPropagationStopped );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Inherited::event( event );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QskInputGrabber::isBlocking( const QPointF& pos ) const
|
||||||
|
{
|
||||||
|
if ( const auto item = parentItem() )
|
||||||
|
return !item->contains( position() + pos );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF QskInputGrabber::grabberRect() const
|
||||||
|
{
|
||||||
|
return m_data->grabberRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskInputGrabber::updateGeometry()
|
||||||
|
{
|
||||||
|
const QRectF rect = grabberRect();
|
||||||
|
if ( rect != geometry() )
|
||||||
|
setGeometry( rect );
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "moc_QskInputGrabber.cpp"
|
|
@ -0,0 +1,36 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QSK_INPUT_GRABBER_H
|
||||||
|
#define QSK_INPUT_GRABBER_H 1
|
||||||
|
|
||||||
|
#include "QskGlobal.h"
|
||||||
|
#include "QskControl.h"
|
||||||
|
|
||||||
|
class QskInputGrabber: public QskControl
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
using Inherited = QskControl;
|
||||||
|
|
||||||
|
public:
|
||||||
|
QskInputGrabber( QQuickItem* parent = nullptr );
|
||||||
|
virtual ~QskInputGrabber();
|
||||||
|
|
||||||
|
virtual QRectF grabberRect() const;
|
||||||
|
virtual bool isBlocking( const QPointF& ) const;
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void updateGeometry();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool event( QEvent* ) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
class PrivateData;
|
||||||
|
std::unique_ptr< PrivateData > m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -4,9 +4,10 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "QskPopup.h"
|
#include "QskPopup.h"
|
||||||
#include "QskQuick.h"
|
#include "QskInputGrabber.h"
|
||||||
#include "QskAspect.h"
|
#include "QskAspect.h"
|
||||||
#include "QskWindow.h"
|
#include "QskWindow.h"
|
||||||
|
#include "QskQuick.h"
|
||||||
#include <QtMath>
|
#include <QtMath>
|
||||||
|
|
||||||
QSK_QT_PRIVATE_BEGIN
|
QSK_QT_PRIVATE_BEGIN
|
||||||
|
@ -40,147 +41,45 @@ static void qskSetFocus( QQuickItem* item, bool on )
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
class InputGrabber final : public QQuickItem
|
class InputGrabber final : public QskInputGrabber
|
||||||
{
|
{
|
||||||
using Inherited = QQuickItem;
|
using Inherited = QskInputGrabber;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
InputGrabber( QskPopup* popup ):
|
InputGrabber( QskPopup* parent ):
|
||||||
Inherited( popup )
|
Inherited( parent )
|
||||||
{
|
{
|
||||||
setObjectName( QStringLiteral( "QskPopupInputGrabber" ) );
|
|
||||||
|
|
||||||
/*
|
|
||||||
We want to receive those events to stop them
|
|
||||||
from being propagated any further
|
|
||||||
*/
|
|
||||||
setAcceptedMouseButtons( Qt::AllButtons );
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
|
|
||||||
setAcceptTouchEvents( true );
|
|
||||||
#endif
|
|
||||||
setAcceptHoverEvents( true );
|
|
||||||
|
|
||||||
QQuickItemPrivate::get( this )->setTransparentForPositioner( true );
|
|
||||||
|
|
||||||
setFlag( QQuickItem::ItemHasContents, false );
|
|
||||||
|
|
||||||
/*
|
|
||||||
The grabber has to be adjusted to the geometry of
|
|
||||||
the parent of the popup, but being a child of the popup its
|
|
||||||
coordinate system is relative to it and needs to be adjusted
|
|
||||||
when the position of the popup changes too.
|
|
||||||
Using a QQuickItemChangeListener instead of connections
|
|
||||||
doesn't make the code much better as we need to deal with
|
|
||||||
how to remove the listener when the grand parent has changed then.
|
|
||||||
*/
|
|
||||||
|
|
||||||
auto method = &InputGrabber::updateGeometry;
|
|
||||||
|
|
||||||
connect( popup, &QQuickItem::xChanged, this, method );
|
|
||||||
connect( popup, &QQuickItem::yChanged, this, method );
|
|
||||||
|
|
||||||
if ( QQuickItem* item = parentItem()->parentItem() )
|
|
||||||
{
|
|
||||||
connect( item, &QQuickItem::xChanged, this, method );
|
|
||||||
connect( item, &QQuickItem::yChanged, this, method );
|
|
||||||
connect( item, &QQuickItem::widthChanged, this, method );
|
|
||||||
connect( item, &QQuickItem::heightChanged, this, method );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateGeometry();
|
virtual void geometryChanged(
|
||||||
}
|
const QRectF& newGeometry, const QRectF& oldGeometry ) override final
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual bool event( QEvent* event ) override final
|
|
||||||
{
|
{
|
||||||
bool doSwallow = false;
|
Inherited::geometryChanged( newGeometry, oldGeometry );
|
||||||
|
|
||||||
switch ( static_cast<int>( event->type() ) )
|
|
||||||
{
|
|
||||||
case QEvent::MouseButtonPress:
|
|
||||||
case QEvent::MouseMove:
|
|
||||||
case QEvent::MouseButtonRelease:
|
|
||||||
{
|
|
||||||
doSwallow = handleMouseEvent( static_cast< QMouseEvent* > ( event ) );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case QEvent::TouchBegin:
|
|
||||||
case QEvent::TouchUpdate:
|
|
||||||
case QEvent::TouchCancel:
|
|
||||||
{
|
|
||||||
doSwallow = handleTouchEvent( static_cast< QTouchEvent* > ( event ) );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case QEvent::Wheel:
|
|
||||||
{
|
|
||||||
doSwallow = handleWheelEvent( static_cast< QWheelEvent* > ( event ) );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case QEvent::HoverEnter:
|
|
||||||
case QEvent::HoverLeave:
|
|
||||||
{
|
|
||||||
doSwallow = handleHoverEvent( static_cast< QHoverEvent* > ( event ) );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( doSwallow )
|
|
||||||
{
|
|
||||||
event->accept();
|
|
||||||
|
|
||||||
if ( auto w = qobject_cast< QskWindow* >( window() ) )
|
|
||||||
w->setEventAcceptance( QskWindow::EventPropagationStopped );
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Inherited::event( event );
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
inline bool handleMouseEvent( const QMouseEvent* event )
|
|
||||||
{
|
|
||||||
return !isInsidePopup( event->localPos() );
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool handleWheelEvent( const QWheelEvent* event )
|
|
||||||
{
|
|
||||||
return !isInsidePopup( event->posF() );
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool handleTouchEvent( const QTouchEvent* )
|
|
||||||
{
|
|
||||||
#if 1
|
|
||||||
return true; // TODO
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool handleHoverEvent( const QHoverEvent* event )
|
|
||||||
{
|
|
||||||
return !isInsidePopup( event->posF() );
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool isInsidePopup( const QPointF& pos ) const
|
|
||||||
{
|
|
||||||
if ( const auto item = parentItem() )
|
|
||||||
return item->contains( position() + pos );
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateGeometry()
|
|
||||||
{
|
|
||||||
if ( auto popup = static_cast< QskPopup* >( parentItem() ) )
|
if ( auto popup = static_cast< QskPopup* >( parentItem() ) )
|
||||||
{
|
{
|
||||||
const QRectF rect = popup->grabberRect();
|
|
||||||
if ( rect != qskItemGeometry( this ) )
|
|
||||||
{
|
|
||||||
qskSetItemGeometry( this, rect );
|
|
||||||
|
|
||||||
if ( popup->hasOverlay() )
|
if ( popup->hasOverlay() )
|
||||||
popup->update();
|
popup->update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool event( QEvent* event ) override final
|
||||||
|
{
|
||||||
|
bool ok = Inherited::event( event );
|
||||||
|
|
||||||
|
if ( event->type() == QEvent::MouseButtonPress )
|
||||||
|
{
|
||||||
|
if ( auto popup = static_cast< QskPopup* >( parentItem() ) )
|
||||||
|
{
|
||||||
|
if ( event->isAccepted() &&
|
||||||
|
( popup->popupFlags() & QskPopup::CloseOnPressOutside ) )
|
||||||
|
{
|
||||||
|
popup->close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -190,6 +89,7 @@ class QskPopup::PrivateData
|
||||||
public:
|
public:
|
||||||
PrivateData():
|
PrivateData():
|
||||||
inputGrabber( nullptr ),
|
inputGrabber( nullptr ),
|
||||||
|
flags( 0 ),
|
||||||
isModal( false ),
|
isModal( false ),
|
||||||
isOpen( false ),
|
isOpen( false ),
|
||||||
autoGrabFocus( true ),
|
autoGrabFocus( true ),
|
||||||
|
@ -199,6 +99,7 @@ public:
|
||||||
|
|
||||||
InputGrabber* inputGrabber;
|
InputGrabber* inputGrabber;
|
||||||
|
|
||||||
|
int flags : 4;
|
||||||
bool isModal : 1;
|
bool isModal : 1;
|
||||||
bool isOpen : 1;
|
bool isOpen : 1;
|
||||||
|
|
||||||
|
@ -226,28 +127,48 @@ QskPopup::~QskPopup()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QskPopup::open()
|
||||||
|
{
|
||||||
|
setFading( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskPopup::close()
|
||||||
|
{
|
||||||
|
const bool wasOpen = m_data->isOpen;
|
||||||
|
m_data->isOpen = false;
|
||||||
|
|
||||||
|
setFading( false );
|
||||||
|
|
||||||
|
if ( wasOpen )
|
||||||
|
{
|
||||||
|
Q_EMIT closed();
|
||||||
|
|
||||||
|
if ( testPopupFlag( DeleteOnClose ) )
|
||||||
|
deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskPopup::setFading( bool on )
|
||||||
|
{
|
||||||
|
setVisible( on );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QskPopup::isOpen() const
|
||||||
|
{
|
||||||
|
return m_data->isOpen;
|
||||||
|
}
|
||||||
|
|
||||||
QRectF QskPopup::overlayRect() const
|
QRectF QskPopup::overlayRect() const
|
||||||
{
|
{
|
||||||
if ( hasOverlay() )
|
if ( hasOverlay() && m_data->inputGrabber )
|
||||||
return grabberRect();
|
return m_data->inputGrabber->grabberRect();
|
||||||
|
|
||||||
return QRectF();
|
|
||||||
}
|
|
||||||
|
|
||||||
QRectF QskPopup::grabberRect() const
|
|
||||||
{
|
|
||||||
if ( const auto item = parentItem() )
|
|
||||||
{
|
|
||||||
if ( isVisible() && m_data->isModal )
|
|
||||||
return QRectF( -position(), QSizeF( item->width(), item->height() ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
return QRectF();
|
return QRectF();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskPopup::updateInputGrabber()
|
void QskPopup::updateInputGrabber()
|
||||||
{
|
{
|
||||||
if ( window() && parentItem() && isVisible() && isModal() )
|
if ( isVisible() && ( isModal() || testPopupFlag( CloseOnPressOutside ) ) )
|
||||||
{
|
{
|
||||||
if ( m_data->inputGrabber == nullptr )
|
if ( m_data->inputGrabber == nullptr )
|
||||||
{
|
{
|
||||||
|
@ -289,6 +210,37 @@ bool QskPopup::isModal() const
|
||||||
return m_data->isModal;
|
return m_data->isModal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QskPopup::setPopupFlags( PopupFlags flags )
|
||||||
|
{
|
||||||
|
m_data->flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
QskPopup::PopupFlags QskPopup::popupFlags() const
|
||||||
|
{
|
||||||
|
return static_cast< PopupFlags >( m_data->flags );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskPopup::setPopupFlag( PopupFlag flag, bool on )
|
||||||
|
{
|
||||||
|
auto flags = m_data->flags;
|
||||||
|
|
||||||
|
if ( on )
|
||||||
|
flags |= flag;
|
||||||
|
else
|
||||||
|
flags &= ~flag;
|
||||||
|
|
||||||
|
if ( flags != m_data->flags )
|
||||||
|
{
|
||||||
|
m_data->flags = flags;
|
||||||
|
updateInputGrabber();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QskPopup::testPopupFlag( PopupFlag flag ) const
|
||||||
|
{
|
||||||
|
return m_data->flags & flag;
|
||||||
|
}
|
||||||
|
|
||||||
void QskPopup::setOverlay( bool on )
|
void QskPopup::setOverlay( bool on )
|
||||||
{
|
{
|
||||||
if ( hasOverlay() != on )
|
if ( hasOverlay() != on )
|
||||||
|
@ -432,12 +384,12 @@ QQuickItem* QskPopup::focusSuccessor() const
|
||||||
|
|
||||||
void QskPopup::aboutToShow()
|
void QskPopup::aboutToShow()
|
||||||
{
|
{
|
||||||
if ( !m_data->isOpen )
|
|
||||||
{
|
|
||||||
if ( m_data->autoGrabFocus )
|
|
||||||
grabFocus( true );
|
|
||||||
|
|
||||||
m_data->isOpen = true;
|
m_data->isOpen = true;
|
||||||
|
|
||||||
|
if ( m_data->autoGrabFocus )
|
||||||
|
{
|
||||||
|
// What to do, when we are hidden below another popup ??
|
||||||
|
grabFocus( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
Inherited::aboutToShow();
|
Inherited::aboutToShow();
|
||||||
|
@ -448,33 +400,19 @@ void QskPopup::itemChange( QQuickItem::ItemChange change,
|
||||||
{
|
{
|
||||||
Inherited::itemChange( change, value );
|
Inherited::itemChange( change, value );
|
||||||
|
|
||||||
switch ( change )
|
if ( change == QQuickItem::ItemVisibleHasChanged )
|
||||||
{
|
{
|
||||||
case QQuickItem::ItemVisibleHasChanged:
|
|
||||||
{
|
|
||||||
updateInputGrabber();
|
|
||||||
|
|
||||||
if ( !value.boolValue )
|
if ( !value.boolValue )
|
||||||
{
|
{
|
||||||
m_data->isOpen = false;
|
|
||||||
grabFocus( false );
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case QQuickItem::ItemParentHasChanged:
|
|
||||||
case QQuickItem::ItemSceneChange:
|
|
||||||
{
|
|
||||||
delete m_data->inputGrabber;
|
|
||||||
m_data->inputGrabber = nullptr;
|
|
||||||
|
|
||||||
updateInputGrabber();
|
updateInputGrabber();
|
||||||
|
|
||||||
break;
|
grabFocus( false );
|
||||||
|
if ( m_data->isOpen )
|
||||||
|
{
|
||||||
|
if ( testPopupFlag( CloseOnHide ) )
|
||||||
|
close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,9 +21,25 @@ class QSK_EXPORT QskPopup : public QskControl
|
||||||
public:
|
public:
|
||||||
QSK_SUBCONTROLS( Overlay )
|
QSK_SUBCONTROLS( Overlay )
|
||||||
|
|
||||||
|
enum PopupFlag
|
||||||
|
{
|
||||||
|
CloseOnHide = 1 << 0,
|
||||||
|
DeleteOnClose = 1 << 1,
|
||||||
|
CloseOnPressOutside = 1 << 2
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_ENUM( PopupFlag )
|
||||||
|
Q_DECLARE_FLAGS( PopupFlags, PopupFlag )
|
||||||
|
|
||||||
QskPopup( QQuickItem* parent = nullptr );
|
QskPopup( QQuickItem* parent = nullptr );
|
||||||
virtual ~QskPopup();
|
virtual ~QskPopup();
|
||||||
|
|
||||||
|
void setPopupFlags( PopupFlags );
|
||||||
|
PopupFlags popupFlags() const;
|
||||||
|
|
||||||
|
void setPopupFlag( PopupFlag, bool on = true );
|
||||||
|
bool testPopupFlag( PopupFlag ) const;
|
||||||
|
|
||||||
void setModal( bool on = true );
|
void setModal( bool on = true );
|
||||||
bool isModal() const;
|
bool isModal() const;
|
||||||
|
|
||||||
|
@ -31,15 +47,21 @@ public:
|
||||||
bool hasOverlay() const;
|
bool hasOverlay() const;
|
||||||
|
|
||||||
virtual QRectF overlayRect() const;
|
virtual QRectF overlayRect() const;
|
||||||
virtual QRectF grabberRect() const;
|
|
||||||
|
|
||||||
|
bool isOpen() const;
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void open();
|
||||||
|
void close();
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
void closed();
|
||||||
void modalChanged( bool );
|
void modalChanged( bool );
|
||||||
void overlayChanged( bool );
|
void overlayChanged( bool );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void aboutToShow() override;
|
virtual void aboutToShow() override;
|
||||||
|
virtual void setFading( bool on );
|
||||||
|
|
||||||
virtual bool event( QEvent* ) override;
|
virtual bool event( QEvent* ) override;
|
||||||
virtual void focusInEvent( QFocusEvent * ) override;
|
virtual void focusInEvent( QFocusEvent * ) override;
|
||||||
|
|
|
@ -7,27 +7,31 @@
|
||||||
#include <QEventLoop>
|
#include <QEventLoop>
|
||||||
#include <QQuickWindow>
|
#include <QQuickWindow>
|
||||||
|
|
||||||
|
static inline void qskSetRejectOnClose( QskDialogSubWindow* subWindow, bool on )
|
||||||
|
{
|
||||||
|
if ( on )
|
||||||
|
{
|
||||||
|
QObject::connect( subWindow, &QskPopup::closed,
|
||||||
|
subWindow, &QskDialogSubWindow::reject );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QObject::disconnect( subWindow, &QskPopup::closed,
|
||||||
|
subWindow, &QskDialogSubWindow::reject );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QskDialogSubWindow::QskDialogSubWindow( QQuickItem* parent ):
|
QskDialogSubWindow::QskDialogSubWindow( QQuickItem* parent ):
|
||||||
Inherited( parent ),
|
Inherited( parent ),
|
||||||
m_result( QskDialog::Rejected ),
|
m_result( QskDialog::Rejected )
|
||||||
m_deleteOnDone( false )
|
|
||||||
{
|
{
|
||||||
|
qskSetRejectOnClose( this, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
QskDialogSubWindow::~QskDialogSubWindow()
|
QskDialogSubWindow::~QskDialogSubWindow()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskDialogSubWindow::setDeleteOnDone( bool on )
|
|
||||||
{
|
|
||||||
m_deleteOnDone = on;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QskDialogSubWindow::deleteOnDone() const
|
|
||||||
{
|
|
||||||
return m_deleteOnDone;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskDialogSubWindow::setResult( QskDialog::DialogCode result )
|
void QskDialogSubWindow::setResult( QskDialog::DialogCode result )
|
||||||
{
|
{
|
||||||
m_result = result;
|
m_result = result;
|
||||||
|
@ -68,17 +72,18 @@ void QskDialogSubWindow::done( QskDialog::DialogCode result )
|
||||||
{
|
{
|
||||||
m_result = result;
|
m_result = result;
|
||||||
|
|
||||||
|
if ( !isOpen() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
qskSetRejectOnClose( this, false );
|
||||||
|
close();
|
||||||
|
|
||||||
Q_EMIT finished( result );
|
Q_EMIT finished( result );
|
||||||
|
|
||||||
if ( result == QskDialog::Accepted )
|
if ( result == QskDialog::Accepted )
|
||||||
Q_EMIT accepted();
|
Q_EMIT accepted();
|
||||||
else
|
else
|
||||||
Q_EMIT rejected();
|
Q_EMIT rejected();
|
||||||
|
|
||||||
hide();
|
|
||||||
|
|
||||||
if ( m_deleteOnDone )
|
|
||||||
deleteLater();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskDialogSubWindow::accept()
|
void QskDialogSubWindow::accept()
|
||||||
|
|
|
@ -20,9 +20,6 @@ public:
|
||||||
QskDialogSubWindow( QQuickItem* parent = nullptr );
|
QskDialogSubWindow( QQuickItem* parent = nullptr );
|
||||||
virtual ~QskDialogSubWindow();
|
virtual ~QskDialogSubWindow();
|
||||||
|
|
||||||
void setDeleteOnDone( bool on );
|
|
||||||
bool deleteOnDone() const;
|
|
||||||
|
|
||||||
Q_INVOKABLE QskDialog::DialogCode result() const;
|
Q_INVOKABLE QskDialog::DialogCode result() const;
|
||||||
Q_INVOKABLE QskDialog::DialogCode exec();
|
Q_INVOKABLE QskDialog::DialogCode exec();
|
||||||
|
|
||||||
|
@ -44,7 +41,6 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QskDialog::DialogCode m_result;
|
QskDialog::DialogCode m_result;
|
||||||
bool m_deleteOnDone : 1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -135,6 +135,7 @@ HEADERS += \
|
||||||
controls/QskGraphicLabel.h \
|
controls/QskGraphicLabel.h \
|
||||||
controls/QskGraphicLabelSkinlet.h \
|
controls/QskGraphicLabelSkinlet.h \
|
||||||
controls/QskHintAnimator.h \
|
controls/QskHintAnimator.h \
|
||||||
|
controls/QskInputGrabber.h \
|
||||||
controls/QskListView.h \
|
controls/QskListView.h \
|
||||||
controls/QskListViewSkinlet.h \
|
controls/QskListViewSkinlet.h \
|
||||||
controls/QskObjectTree.h \
|
controls/QskObjectTree.h \
|
||||||
|
@ -200,6 +201,7 @@ SOURCES += \
|
||||||
controls/QskGraphicLabel.cpp \
|
controls/QskGraphicLabel.cpp \
|
||||||
controls/QskGraphicLabelSkinlet.cpp \
|
controls/QskGraphicLabelSkinlet.cpp \
|
||||||
controls/QskHintAnimator.cpp \
|
controls/QskHintAnimator.cpp \
|
||||||
|
controls/QskInputGrabber.cpp \
|
||||||
controls/QskListView.cpp \
|
controls/QskListView.cpp \
|
||||||
controls/QskListViewSkinlet.cpp \
|
controls/QskListViewSkinlet.cpp \
|
||||||
controls/QskObjectTree.cpp \
|
controls/QskObjectTree.cpp \
|
||||||
|
|
Loading…
Reference in New Issue