Skip to content
Permalink
Browse files

Make the GUI work without crashing (avoid embedded event loop)

  • Loading branch information
wonder-sk committed Aug 24, 2018
1 parent f08ebab commit 832d27c29edcf445606c71a789f5d610ed89ab2f
@@ -419,6 +419,9 @@ void QgsCameraController::setLookingAtPoint( const QgsVector3D &point, float dis

void QgsCameraController::setCameraPose( const QgsCameraPose &camPose )
{
if ( camPose == mCameraPose )
return;

mCameraPose = camPose;

if ( mCamera )
@@ -26,6 +26,7 @@
QgsLayoutItem3DMap::QgsLayoutItem3DMap( QgsLayout *layout )
: QgsLayoutItem( layout )
{
connect( this, &QgsLayoutItem::sizePositionChanged, this, &QgsLayoutItem3DMap::onSizePositionChanged );
}

QgsLayoutItem3DMap::~QgsLayoutItem3DMap() = default;
@@ -43,30 +44,80 @@ int QgsLayoutItem3DMap::type() const

void QgsLayoutItem3DMap::draw( QgsLayoutItemRenderContext &context )
{
QgsRenderContext &ctx = context.renderContext();
QPainter *painter = ctx.painter();

int w = static_cast<int>( std::ceil( rect().width() * ctx.scaleFactor() ) );
int h = static_cast<int>( std::ceil( rect().height() * ctx.scaleFactor() ) );
QRect r( 0, 0, w, h );

painter->save();

if ( !mSettings )
{
painter->drawText( r, Qt::AlignCenter, tr( "Scene not set" ) );
painter->restore();
return;
}

if ( !mCapturedImage.isNull() )
{
painter->drawImage( r, mCapturedImage );
painter->restore();
return;
}

// we do not have a cached image of the rendered scene - let's request one from the engine

painter->drawText( r, Qt::AlignCenter, tr( "Loading" ) );
painter->restore();

QgsOffscreen3DEngine engine;
QSizeF sizePixels = mLayout->renderContext().measurementConverter().convert( sizeWithUnits(), QgsUnitTypes::LayoutPixels ).toQSizeF();
engine.setSize( QSize( static_cast<int>( std::ceil( sizePixels.width() ) ),
static_cast<int>( std::ceil( sizePixels.height() ) ) ) );
QSize sizePixelsInt = QSize( static_cast<int>( std::ceil( sizePixels.width() ) ),
static_cast<int>( std::ceil( sizePixels.height() ) ) );

Qgs3DMapScene *scene = new Qgs3DMapScene( *mSettings, &engine );
engine.setRootEntity( scene );
if ( !mEngine )
{
mEngine.reset( new QgsOffscreen3DEngine );
connect( mEngine.get(), &QgsAbstract3DEngine::imageCaptured, this, &QgsLayoutItem3DMap::onImageCaptured );

scene->cameraController()->setCameraPose( mCameraPose );
mEngine->setSize( sizePixelsInt );

// XXX this should not be needed, but without it the scene often
// is not completely ready (e.g. a missing terrain tile).
// leaving it here until a more robust solution is found...
Qgs3DUtils::captureSceneImage( engine, scene );
mScene = new Qgs3DMapScene( *mSettings, mEngine.get() );
connect( mScene, &Qgs3DMapScene::sceneStateChanged, this, &QgsLayoutItem3DMap::onSceneStateChanged );

QImage img = Qgs3DUtils::captureSceneImage( engine, scene );
mEngine->setRootEntity( mScene );
}

QgsRenderContext &ctx = context.renderContext();
ctx.painter()->drawImage( 0, 0, img );
if ( mEngine->size() != sizePixelsInt )
mEngine->setSize( sizePixelsInt );

mScene->cameraController()->setCameraPose( mCameraPose );

onSceneStateChanged();
}

void QgsLayoutItem3DMap::onImageCaptured( const QImage &img )
{
mCapturedImage = img;
update();
}

void QgsLayoutItem3DMap::onSceneStateChanged()
{
if ( mCapturedImage.isNull() && mScene->sceneState() == Qgs3DMapScene::Ready )
{
mEngine->requestCaptureImage();
}
}

void QgsLayoutItem3DMap::onSizePositionChanged()
{
mCapturedImage = QImage();
update();
}


bool QgsLayoutItem3DMap::writePropertiesToElement( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const
{
if ( mSettings )
@@ -83,6 +134,7 @@ bool QgsLayoutItem3DMap::writePropertiesToElement( QDomElement &element, QDomDoc

bool QgsLayoutItem3DMap::readPropertiesFromElement( const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context )
{
Q_UNUSED( document );
QDomElement elemSettings = element.firstChildElement( "qgis3d" );
if ( !elemSettings.isNull() )
{
@@ -102,4 +154,20 @@ bool QgsLayoutItem3DMap::readPropertiesFromElement( const QDomElement &element,
void QgsLayoutItem3DMap::setMapSettings( Qgs3DMapSettings *settings )
{
mSettings.reset( settings );

mEngine.reset();
mScene = nullptr;

mCapturedImage = QImage();
update();
}

void QgsLayoutItem3DMap::setCameraPose( const QgsCameraPose &pose )
{
if ( mCameraPose == pose )
return;

mCameraPose = pose;
mCapturedImage = QImage();
update();
}
@@ -23,7 +23,9 @@
#include "qgscamerapose.h"


class Qgs3DMapScene;
class Qgs3DMapSettings;
class QgsOffscreen3DEngine;

/**
* \ingroup 3d
@@ -74,7 +76,7 @@ class _3D_EXPORT QgsLayoutItem3DMap : public QgsLayoutItem
virtual int type() const override;

//! Configures camera view
void setCameraPose( const QgsCameraPose &pose ) { mCameraPose = pose; }
void setCameraPose( const QgsCameraPose &pose );
//! Returns camera view
QgsCameraPose cameraPose() const { return mCameraPose; }

@@ -92,9 +94,18 @@ class _3D_EXPORT QgsLayoutItem3DMap : public QgsLayoutItem
bool writePropertiesToElement( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const override;
bool readPropertiesFromElement( const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context ) override;

private slots:
void onImageCaptured( const QImage &img );
void onSceneStateChanged();
void onSizePositionChanged();

private:
std::unique_ptr<Qgs3DMapSettings> mSettings;
std::unique_ptr<QgsOffscreen3DEngine> mEngine;
Qgs3DMapScene *mScene = nullptr; //!< 3D scene (owned by the 3D engine)
QImage mCapturedImage;
QgsCameraPose mCameraPose;
bool mDrawing = false;
};

#endif // QGSLAYOUTITEM3DMAP_H
@@ -27,6 +27,10 @@ QgsLayout3DMapWidget::QgsLayout3DMapWidget( QgsLayoutItem3DMap *map3D )
{
setupUi( this );

//add widget for general composer item properties
mItemPropertiesWidget = new QgsLayoutItemPropertiesWidget( this, map3D );
mainLayout->addWidget( mItemPropertiesWidget );

mMenu3DCanvases = new QMenu( this );
mCopySettingsButton->setMenu( mMenu3DCanvases );
connect( mMenu3DCanvases, &QMenu::aboutToShow, this, [ = ]
@@ -34,6 +34,7 @@ class QgsLayout3DMapWidget : public QgsLayoutItemBaseWidget, private Ui::QgsLayo

private:
QPointer< QgsLayoutItem3DMap > mMap3D;
QgsLayoutItemPropertiesWidget *mItemPropertiesWidget = nullptr;
QMenu *mMenu3DCanvases = nullptr;
};

@@ -54,12 +54,12 @@
<property name="geometry">
<rect>
<x>0</x>
<y>-65</y>
<y>0</y>
<width>510</width>
<height>635</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<layout class="QVBoxLayout" name="mainLayout">
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">

0 comments on commit 832d27c

Please sign in to comment.
You can’t perform that action at this time.