fixed for multiple windows with different thread contexts

This commit is contained in:
Uwe Rathmann 2018-04-17 14:46:50 +02:00
parent 34cc82dd70
commit a950203e7b
1 changed files with 72 additions and 17 deletions

View File

@ -9,6 +9,9 @@
#include <QQuickWindow> #include <QQuickWindow>
#include <QGlobalStatic> #include <QGlobalStatic>
#include <QThread>
#include <QMutexLocker>
#include <QHash>
QSK_QT_PRIVATE_BEGIN QSK_QT_PRIVATE_BEGIN
#include <private/qquicktext_p.h> #include <private/qquicktext_p.h>
@ -79,18 +82,23 @@ namespace
setWrapMode( static_cast< QQuickText::WrapMode >( options.wrapMode() ) ); setWrapMode( static_cast< QQuickText::WrapMode >( options.wrapMode() ) );
} }
void begin() inline void begin()
{ {
classBegin(); classBegin();
QQuickTextPrivate::get( this )->updateOnComponentComplete = true; QQuickTextPrivate::get( this )->updateOnComponentComplete = true;
} }
void end() inline void end()
{ {
componentComplete(); componentComplete();
} }
QRectF layedOutTextRect() const inline void reset()
{
setText( QString() );
}
inline QRectF layedOutTextRect() const
{ {
auto that = const_cast< TextItem* >( this ); auto that = const_cast< TextItem* >( this );
return QQuickTextPrivate::get( that )->layedOutTextRect; return QQuickTextPrivate::get( that )->layedOutTextRect;
@ -118,6 +126,46 @@ namespace
return nullptr; return nullptr;
} }
}; };
class TextItemMap
{
public:
~TextItemMap()
{
qDeleteAll( m_hash );
}
inline TextItem* item()
{
const auto thread = QThread::currentThread();
QMutexLocker locker( &m_mutex );
auto it = m_hash.constFind( thread );
if ( it == m_hash.constEnd() )
{
auto textItem = new TextItem();
QObject::connect( thread, &QThread::finished,
textItem, [this, thread] { removeItem( thread ); } );
m_hash.insert( thread, textItem );
return textItem;
}
return it.value();
}
private:
void removeItem( const QThread* thread )
{
auto textItem = m_hash.take( thread );
if ( textItem )
textItem->deleteLater();
}
QMutex m_mutex;
QHash< const QThread*, TextItem* > m_hash;
};
} }
/* /*
@ -125,31 +173,34 @@ namespace
better use different items as we might end up in events internally better use different items as we might end up in events internally
being sent, that leads to crashes because of it being sent, that leads to crashes because of it
*/ */
Q_GLOBAL_STATIC( TextItem, qskRenderHelper ) Q_GLOBAL_STATIC( TextItemMap, qskTextItemMap )
Q_GLOBAL_STATIC( TextItem, qskLayoutHelper )
QSizeF QskRichTextRenderer::textSize( const QString& text, QSizeF QskRichTextRenderer::textSize( const QString& text,
const QFont& font, const QskTextOptions& options ) const QFont& font, const QskTextOptions& options )
{ {
auto& item = *qskLayoutHelper; auto& textItem = *qskTextItemMap->item();
item.begin(); textItem.begin();
item.setFont( font ); textItem.setFont( font );
item.setOptions( options ); textItem.setOptions( options );
item.setWidth( -1 ); textItem.setWidth( -1 );
item.setText( text ); textItem.setText( text );
item.end(); textItem.end();
return QSizeF( item.implicitWidth(), item.implicitHeight() ); const QSizeF sz( textItem.implicitWidth(), textItem.implicitHeight() );
textItem.reset();
return sz;
} }
QRectF QskRichTextRenderer::textRect( const QString& text, QRectF QskRichTextRenderer::textRect( const QString& text,
const QFont& font, const QskTextOptions& options, const QSizeF& size ) const QFont& font, const QskTextOptions& options, const QSizeF& size )
{ {
auto& textItem = *qskLayoutHelper; auto& textItem = *qskTextItemMap->item();
textItem.begin(); textItem.begin();
@ -164,7 +215,11 @@ QRectF QskRichTextRenderer::textRect( const QString& text,
textItem.end(); textItem.end();
return textItem.layedOutTextRect(); const auto rect = textItem.layedOutTextRect();
textItem.reset();
return rect;
} }
void QskRichTextRenderer::updateNode( const QString& text, void QskRichTextRenderer::updateNode( const QString& text,
@ -176,7 +231,7 @@ void QskRichTextRenderer::updateNode( const QString& text,
// are we killing internal caches of QQuickText, when always using // are we killing internal caches of QQuickText, when always using
// the same item for the creation the text nodes. TODO ... // the same item for the creation the text nodes. TODO ...
auto& textItem = *qskRenderHelper; auto& textItem = *qskTextItemMap->item();
textItem.begin(); textItem.begin();
@ -220,5 +275,5 @@ void QskRichTextRenderer::updateNode( const QString& text,
} }
textItem.updateTextNode( item->window(), node ); textItem.updateTextNode( item->window(), node );
textItem.setText( QString() ); textItem.reset();
} }