diff --git a/src/controls/QskControl.cpp b/src/controls/QskControl.cpp index 83e0190b..600c38cb 100644 --- a/src/controls/QskControl.cpp +++ b/src/controls/QskControl.cpp @@ -18,15 +18,11 @@ QSK_QT_PRIVATE_BEGIN #include -#include #if defined( QT_DEBUG ) #include #endif QSK_QT_PRIVATE_END -#include -#include - #include #include #include @@ -46,206 +42,6 @@ static inline void qskSendEventTo( QObject* object, QEvent::Type type ) QCoreApplication::sendEvent( object, &event ); } -QRectF qskItemRect( const QQuickItem* item ) -{ - auto d = QQuickItemPrivate::get( item ); - return QRectF( 0, 0, d->width, d->height ); -} - -QRectF qskItemGeometry( const QQuickItem* item ) -{ - auto d = QQuickItemPrivate::get( item ); - return QRectF( d->x, d->y, d->width, d->height ); -} - -void qskSetItemGeometry( QQuickItem* item, const QRectF& rect ) -{ - if ( auto control = qobject_cast< QskControl* >( item ) ) - { - control->setGeometry( rect ); - } - else - { - item->setPosition( rect.topLeft() ); - item->setSize( rect.size() ); - } -} - -bool qskIsItemComplete( const QQuickItem* item ) -{ - return QQuickItemPrivate::get( item )->componentComplete; -} - -bool qskIsAncestorOf( const QQuickItem* item, const QQuickItem* child ) -{ - if ( item == nullptr || child == nullptr ) - return false; - -#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) - return item->isAncestorOf( child ); -#else - while ( child ) - { - if ( child == item ) - return true; - - child = child->parentItem(); - } - - return false; -#endif -} - -bool qskIsTabFence( const QQuickItem* item ) -{ - if ( item == nullptr ) - return false; - - return QQuickItemPrivate::get( item )->isTabFence; -} - -bool qskIsShortcutScope( const QQuickItem* item ) -{ - if ( item == nullptr ) - return false; - - /* - We might have something like CTRL+W to close a "window". - But in Qt/Quick a window is not necessarily a QQuickWindow - like we have f.e QskSubWindow. - - Maybe it's worth to introduce a shortcutScope flag but for - the moment we simply use the isFocusScope/isTabFence combination, - that should usually be set for those "windows". - */ - - return item->isFocusScope() && QQuickItemPrivate::get( item )->isTabFence; -} - -bool qskIsTransparentForPositioner( const QQuickItem* item ) -{ - if ( item == nullptr ) - return true; - - return QQuickItemPrivate::get( item )->isTransparentForPositioner(); -} - -QQuickItem* qskNearestFocusScope( const QQuickItem* item ) -{ - if ( item ) - { - for ( QQuickItem* scope = item->parentItem(); - scope != nullptr; scope = scope->parentItem() ) - { - if ( scope->isFocusScope() ) - return scope; - } - - /* - As the default setting of the root item is to be a focus scope - we usually never get here - beside the flag has been explicitely - disabled in application code. - */ - } - - return nullptr; -} - -void qskForceActiveFocus( QQuickItem* item, Qt::FocusReason reason ) -{ - /* - For unknown reasons Qt::PopupFocusReason is blocked inside of - QQuickItem::setFocus and so we can't use QQuickItem::forceActiveFocus - */ - - if ( item == nullptr || item->window() == nullptr ) - return; - - auto wp = QQuickWindowPrivate::get( item->window() ); - - while ( const auto scope = qskNearestFocusScope( item ) ) - { - wp->setFocusInScope( scope, item, reason ); - item = scope; - } -} - -QQuickItem* qskInputContextItem() -{ - /* - The item that is connected to the input context. - - often the item having the active focus. - */ - - QQuickItem* inputItem = nullptr; - - /* - We could also get the inputContext from QInputMethodPrivate - but for some reason the gcc sanitizer reports errors - when using it. So let's go with QGuiApplicationPrivate. - */ - const auto inputContext = - QGuiApplicationPrivate::platformIntegration()->inputContext(); - - if ( inputContext && inputContext->isInputPanelVisible() ) - { - /* - QskInputContext allows to navigate inside the input panel - without losing the connected input item - */ - - QMetaObject::invokeMethod( inputContext, "inputItem", - Qt::DirectConnection, Q_RETURN_ARG( QQuickItem*, inputItem ) ); - } - - return inputItem; -} - -void qskUpdateInputMethod( const QQuickItem* item, Qt::InputMethodQueries queries ) -{ - if ( item == nullptr ) - return; - -#if 1 - if ( !( item->flags() & QQuickItem::ItemAcceptsInputMethod ) ) - return; -#endif - - bool doUpdate; - - if ( const QQuickItem* inputItem = qskInputContextItem() ) - doUpdate = ( item == inputItem ); - else - doUpdate = item->hasActiveFocus(); - - if ( doUpdate ) - QGuiApplication::inputMethod()->update( queries ); -} - -QList< QQuickItem* > qskPaintOrderChildItems( const QQuickItem* item ) -{ - if ( item ) - return QQuickItemPrivate::get( item )->paintOrderChildItems(); - - return QList< QQuickItem* >(); -} - -const QSGNode* qskItemNode( const QQuickItem* item ) -{ - if ( item == nullptr ) - return nullptr; - - return QQuickItemPrivate::get( item )->itemNodeInstance; -} - -const QSGNode* qskPaintNode( const QQuickItem* item ) -{ - if ( item == nullptr ) - return nullptr; - - return QQuickItemPrivate::get( item )->paintNode; -} - static inline controlFlags_t qskControlFlags() { // we are only interested in the first 8 bits @@ -540,7 +336,7 @@ QskControl::QskControl( QQuickItem* parent ): } // since Qt 5.10 we have QQuickItem::ItemEnabledHasChanged -#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) +#if QT_VERSION < QT_VERSION_CHECK( 5, 10, 0 ) /* Setting up this connections slows down the time needed for construction by almost 100%. Would be nice to diff --git a/src/controls/QskQuick.cpp b/src/controls/QskQuick.cpp new file mode 100644 index 00000000..aa6d4d60 --- /dev/null +++ b/src/controls/QskQuick.cpp @@ -0,0 +1,215 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * This file may be used under the terms of the QSkinny License, Version 1.0 + *****************************************************************************/ + +#include "QskQuick.h" +#include "QskControl.h" + +QSK_QT_PRIVATE_BEGIN +#include +#include +QSK_QT_PRIVATE_END + +#include +#include + +QRectF qskItemRect( const QQuickItem* item ) +{ + auto d = QQuickItemPrivate::get( item ); + return QRectF( 0, 0, d->width, d->height ); +} + +QRectF qskItemGeometry( const QQuickItem* item ) +{ + auto d = QQuickItemPrivate::get( item ); + return QRectF( d->x, d->y, d->width, d->height ); +} + +void qskSetItemGeometry( QQuickItem* item, const QRectF& rect ) +{ + if ( auto control = qobject_cast< QskControl* >( item ) ) + { + control->setGeometry( rect ); + } + else + { + item->setPosition( rect.topLeft() ); + item->setSize( rect.size() ); + } +} + +bool qskIsItemComplete( const QQuickItem* item ) +{ + return QQuickItemPrivate::get( item )->componentComplete; +} + +bool qskIsAncestorOf( const QQuickItem* item, const QQuickItem* child ) +{ + if ( item == nullptr || child == nullptr ) + return false; + +#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) + return item->isAncestorOf( child ); +#else + while ( child ) + { + if ( child == item ) + return true; + + child = child->parentItem(); + } + + return false; +#endif +} + +bool qskIsTabFence( const QQuickItem* item ) +{ + if ( item == nullptr ) + return false; + + return QQuickItemPrivate::get( item )->isTabFence; +} + +bool qskIsShortcutScope( const QQuickItem* item ) +{ + if ( item == nullptr ) + return false; + + /* + We might have something like CTRL+W to close a "window". + But in Qt/Quick a window is not necessarily a QQuickWindow + like we have f.e QskSubWindow. + + Maybe it's worth to introduce a shortcutScope flag but for + the moment we simply use the isFocusScope/isTabFence combination, + that should usually be set for those "windows". + */ + + return item->isFocusScope() && QQuickItemPrivate::get( item )->isTabFence; +} + +bool qskIsTransparentForPositioner( const QQuickItem* item ) +{ + if ( item == nullptr ) + return true; + + return QQuickItemPrivate::get( item )->isTransparentForPositioner(); +} + +QQuickItem* qskNearestFocusScope( const QQuickItem* item ) +{ + if ( item ) + { + for ( QQuickItem* scope = item->parentItem(); + scope != nullptr; scope = scope->parentItem() ) + { + if ( scope->isFocusScope() ) + return scope; + } + + /* + As the default setting of the root item is to be a focus scope + we usually never get here - beside the flag has been explicitely + disabled in application code. + */ + } + + return nullptr; +} + +void qskForceActiveFocus( QQuickItem* item, Qt::FocusReason reason ) +{ + /* + For unknown reasons Qt::PopupFocusReason is blocked inside of + QQuickItem::setFocus and so we can't use QQuickItem::forceActiveFocus + */ + + if ( item == nullptr || item->window() == nullptr ) + return; + + auto wp = QQuickWindowPrivate::get( item->window() ); + + while ( const auto scope = qskNearestFocusScope( item ) ) + { + wp->setFocusInScope( scope, item, reason ); + item = scope; + } +} + +QQuickItem* qskInputContextItem() +{ + /* + The item that is connected to the input context. + - often the item having the active focus. + */ + + QQuickItem* inputItem = nullptr; + + /* + We could also get the inputContext from QInputMethodPrivate + but for some reason the gcc sanitizer reports errors + when using it. So let's go with QGuiApplicationPrivate. + */ + const auto inputContext = + QGuiApplicationPrivate::platformIntegration()->inputContext(); + + if ( inputContext && inputContext->isInputPanelVisible() ) + { + /* + QskInputContext allows to navigate inside the input panel + without losing the connected input item + */ + + QMetaObject::invokeMethod( inputContext, "inputItem", + Qt::DirectConnection, Q_RETURN_ARG( QQuickItem*, inputItem ) ); + } + + return inputItem; +} + +void qskUpdateInputMethod( const QQuickItem* item, Qt::InputMethodQueries queries ) +{ + if ( item == nullptr ) + return; + +#if 1 + if ( !( item->flags() & QQuickItem::ItemAcceptsInputMethod ) ) + return; +#endif + + bool doUpdate; + + if ( const QQuickItem* inputItem = qskInputContextItem() ) + doUpdate = ( item == inputItem ); + else + doUpdate = item->hasActiveFocus(); + + if ( doUpdate ) + QGuiApplication::inputMethod()->update( queries ); +} + +QList< QQuickItem* > qskPaintOrderChildItems( const QQuickItem* item ) +{ + if ( item ) + return QQuickItemPrivate::get( item )->paintOrderChildItems(); + + return QList< QQuickItem* >(); +} + +const QSGNode* qskItemNode( const QQuickItem* item ) +{ + if ( item == nullptr ) + return nullptr; + + return QQuickItemPrivate::get( item )->itemNodeInstance; +} + +const QSGNode* qskPaintNode( const QQuickItem* item ) +{ + if ( item == nullptr ) + return nullptr; + + return QQuickItemPrivate::get( item )->paintNode; +} diff --git a/src/controls/QskQuick.h b/src/controls/QskQuick.h new file mode 100644 index 00000000..35825bcb --- /dev/null +++ b/src/controls/QskQuick.h @@ -0,0 +1,39 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * This file may be used under the terms of the QSkinny License, Version 1.0 + *****************************************************************************/ + +#ifndef QSK_QUICK_H +#define QSK_QUICK_H 1 + +#include "QskGlobal.h" +#include + +/* + Exporting methods from QQuickItemPrivate, that should be part + of QQuickItem. + */ + +QSK_EXPORT bool qskIsItemComplete( const QQuickItem* item ); +QSK_EXPORT bool qskIsAncestorOf( const QQuickItem* item, const QQuickItem* child ); +QSK_EXPORT bool qskIsTransparentForPositioner( const QQuickItem* ); +QSK_EXPORT bool qskIsTabFence( const QQuickItem* ); +QSK_EXPORT bool qskIsShortcutScope( const QQuickItem* ); + +QSK_EXPORT QRectF qskItemRect( const QQuickItem* ); + +QSK_EXPORT QRectF qskItemGeometry( const QQuickItem* ); +QSK_EXPORT void qskSetItemGeometry( QQuickItem*, const QRectF& ); + +QSK_EXPORT QQuickItem* qskNearestFocusScope( const QQuickItem* ); +QSK_EXPORT void qskForceActiveFocus( QQuickItem*, Qt::FocusReason ); + +QSK_EXPORT QList< QQuickItem* > qskPaintOrderChildItems( const QQuickItem* ); + +QSK_EXPORT void qskUpdateInputMethod( const QQuickItem*, Qt::InputMethodQueries ); +QSK_EXPORT QQuickItem* qskInputContextItem(); + +QSK_EXPORT const QSGNode* qskItemNode( const QQuickItem* ); +QSK_EXPORT const QSGNode* qskPaintNode( const QQuickItem* ); + +#endif diff --git a/src/src.pro b/src/src.pro index 174dc273..242d1a20 100644 --- a/src/src.pro +++ b/src/src.pro @@ -145,6 +145,7 @@ HEADERS += \ controls/QskPopupSkinlet.h \ controls/QskPushButton.h \ controls/QskPushButtonSkinlet.h \ + controls/QskQuick.h \ controls/QskRangeControl.h \ controls/QskResizable.h \ controls/QskRgbValue.h \ @@ -210,6 +211,7 @@ SOURCES += \ controls/QskPopupSkinlet.cpp \ controls/QskPushButton.cpp \ controls/QskPushButtonSkinlet.cpp \ + controls/QskQuick.cpp \ controls/QskRangeControl.cpp \ controls/QskResizable.cpp \ controls/QskRgbValue.cpp \