Skip to content

Commit

Permalink
GUI for the 3D map print layout item
Browse files Browse the repository at this point in the history
  • Loading branch information
wonder-sk committed Aug 23, 2018
1 parent d4a3f68 commit f08ebab
Show file tree
Hide file tree
Showing 7 changed files with 154 additions and 9 deletions.
25 changes: 25 additions & 0 deletions src/3d/qgscamerapose.cpp
Expand Up @@ -17,6 +17,31 @@

#include <Qt3DRender/QCamera>

#include <QDomDocument>

QDomElement QgsCameraPose::writeXml( QDomDocument &doc ) const
{
QDomElement elemCamera = doc.createElement( "camera-pose" );
elemCamera.setAttribute( QStringLiteral( "x" ), mCenterPoint.x() );
elemCamera.setAttribute( QStringLiteral( "y" ), mCenterPoint.y() );
elemCamera.setAttribute( QStringLiteral( "z" ), mCenterPoint.z() );
elemCamera.setAttribute( QStringLiteral( "dist" ), mDistanceFromCenterPoint );
elemCamera.setAttribute( QStringLiteral( "pitch" ), mPitchAngle );
elemCamera.setAttribute( QStringLiteral( "heading" ), mHeadingAngle );
return elemCamera;
}

void QgsCameraPose::readXml( const QDomElement &elem )
{
double x = elem.attribute( QStringLiteral( "x" ) ).toDouble();
double y = elem.attribute( QStringLiteral( "y" ) ).toDouble();
double z = elem.attribute( QStringLiteral( "z" ) ).toDouble();
mCenterPoint = QgsVector3D( x, y, z );

mDistanceFromCenterPoint = elem.attribute( QStringLiteral( "dist" ) ).toFloat();
mPitchAngle = elem.attribute( QStringLiteral( "pitch" ) ).toFloat();
mHeadingAngle = elem.attribute( QStringLiteral( "heading" ) ).toFloat();
}

void QgsCameraPose::updateCamera( Qt3DRender::QCamera *camera )
{
Expand Down
8 changes: 8 additions & 0 deletions src/3d/qgscamerapose.h
Expand Up @@ -25,6 +25,9 @@ namespace Qt3DRender
class QCamera;
}

class QDomDocument;
class QDomElement;

/**
* \ingroup 3d
* Class that encapsulates camera pose in a 3D scene. The pose is defined with the following parameters:
Expand Down Expand Up @@ -62,6 +65,11 @@ class _3D_EXPORT QgsCameraPose
//! Update Qt3D camera view matrix based on the pose
void updateCamera( Qt3DRender::QCamera *camera );

//! Writes configuration to a new DOM element and returns it
QDomElement writeXml( QDomDocument &doc ) const;
//! Reads configuration from a DOM element previously written using writeXml()
void readXml( const QDomElement &elem );

bool operator==( const QgsCameraPose &other ) const
{
return mCenterPoint == other.mCenterPoint &&
Expand Down
32 changes: 32 additions & 0 deletions src/3d/qgslayoutitem3dmap.cpp
Expand Up @@ -67,6 +67,38 @@ void QgsLayoutItem3DMap::draw( QgsLayoutItemRenderContext &context )
ctx.painter()->drawImage( 0, 0, img );
}

bool QgsLayoutItem3DMap::writePropertiesToElement( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const
{
if ( mSettings )
{
QDomElement elemSettings = mSettings->writeXml( document, context );
element.appendChild( elemSettings );
}

QDomElement elemCameraPose = mCameraPose.writeXml( document );
element.appendChild( elemCameraPose );

return true;
}

bool QgsLayoutItem3DMap::readPropertiesFromElement( const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context )
{
QDomElement elemSettings = element.firstChildElement( "qgis3d" );
if ( !elemSettings.isNull() )
{
mSettings.reset( new Qgs3DMapSettings );
mSettings->readXml( elemSettings, context );
if ( mLayout->project() )
mSettings->resolveReferences( *mLayout->project() );
}

QDomElement elemCameraPose = element.firstChildElement( "camera-pose" );
if ( !elemCameraPose.isNull() )
mCameraPose.readXml( elemCameraPose );

return true;
}

void QgsLayoutItem3DMap::setMapSettings( Qgs3DMapSettings *settings )
{
mSettings.reset( settings );
Expand Down
7 changes: 5 additions & 2 deletions src/3d/qgslayoutitem3dmap.h
Expand Up @@ -73,8 +73,6 @@ class _3D_EXPORT QgsLayoutItem3DMap : public QgsLayoutItem

virtual int type() const override;

virtual void draw( QgsLayoutItemRenderContext &context ) override;

//! Configures camera view
void setCameraPose( const QgsCameraPose &pose ) { mCameraPose = pose; }
//! Returns camera view
Expand All @@ -89,6 +87,11 @@ class _3D_EXPORT QgsLayoutItem3DMap : public QgsLayoutItem
//! Returns map scene. May be a null pointer if not yet configured.
Qgs3DMapSettings *mapSettings() const { return mSettings.get(); }

protected:
void draw( QgsLayoutItemRenderContext &context ) override;
bool writePropertiesToElement( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const override;
bool readPropertiesFromElement( const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context ) override;

private:
std::unique_ptr<Qgs3DMapSettings> mSettings;
QgsCameraPose mCameraPose;
Expand Down
65 changes: 65 additions & 0 deletions src/app/layout/qgslayout3dmapwidget.cpp
Expand Up @@ -15,10 +15,75 @@

#include "qgslayout3dmapwidget.h"

#include "qgisapp.h"
#include "qgs3dmapcanvas.h"
#include "qgs3dmapcanvasdockwidget.h"
#include "qgs3dmapsettings.h"
#include <QMenu>

QgsLayout3DMapWidget::QgsLayout3DMapWidget( QgsLayoutItem3DMap *map3D )
: QgsLayoutItemBaseWidget( nullptr, map3D )
, mMap3D( map3D )
{
setupUi( this );

mMenu3DCanvases = new QMenu( this );
mCopySettingsButton->setMenu( mMenu3DCanvases );
connect( mMenu3DCanvases, &QMenu::aboutToShow, this, [ = ]
{
const QList<Qgs3DMapCanvasDockWidget *> lst = QgisApp::instance()->findChildren<Qgs3DMapCanvasDockWidget *>();
mMenu3DCanvases->clear();
for ( auto dock : lst )
{
QAction *a = mMenu3DCanvases->addAction( dock->mapCanvas3D()->objectName(), this, &QgsLayout3DMapWidget::copy3DMapSettings );
// need to use a custom property for identification because Qt likes to add "&" to the action text
a->setProperty( "name", dock->mapCanvas3D()->objectName() );
}
if ( lst.isEmpty() )
{
mMenu3DCanvases->addAction( tr( "No 3D maps defined" ) )->setEnabled( false );
}
} );

QgsCameraPose pose = mMap3D->cameraPose();
mCenterXSpinBox->setValue( pose.centerPoint().x() );
mCenterYSpinBox->setValue( pose.centerPoint().y() );
mCenterZSpinBox->setValue( pose.centerPoint().z() );
mDistanceToCenterSpinBox->setValue( pose.distanceFromCenterPoint() );
mPitchAngleSpinBox->setValue( pose.pitchAngle() );
mHeadingAngleSpinBox->setValue( pose.headingAngle() );

QList<QgsDoubleSpinBox *> lst;
lst << mCenterXSpinBox << mCenterXSpinBox << mCenterXSpinBox << mDistanceToCenterSpinBox << mPitchAngleSpinBox << mHeadingAngleSpinBox;
for ( QgsDoubleSpinBox *spinBox : lst )
connect( spinBox, qgis::overload<double>::of( &QgsDoubleSpinBox::valueChanged ), this, &QgsLayout3DMapWidget::updateCameraPose );
}

void QgsLayout3DMapWidget::copy3DMapSettings()
{
QAction *action = qobject_cast<QAction *>( sender() );
if ( !action )
return;

QString actionText = action->property( "name" ).toString();
const QList<Qgs3DMapCanvasDockWidget *> lst = QgisApp::instance()->findChildren<Qgs3DMapCanvasDockWidget *>();
for ( auto dock : lst )
{
QString objName = dock->mapCanvas3D()->objectName();
if ( objName == actionText )
{
mMap3D->setMapSettings( new Qgs3DMapSettings( *dock->mapCanvas3D()->map() ) );
break;
}
}
}

void QgsLayout3DMapWidget::updateCameraPose()
{
QgsCameraPose pose;
pose.setCenterPoint( QgsVector3D( mCenterXSpinBox->value(), mCenterYSpinBox->value(), mCenterZSpinBox->value() ) );
pose.setDistanceFromCenterPoint( mDistanceToCenterSpinBox->value() );
pose.setPitchAngle( mPitchAngleSpinBox->value() );
pose.setHeadingAngle( mHeadingAngleSpinBox->value() );
mMap3D->setCameraPose( pose );
}
5 changes: 5 additions & 0 deletions src/app/layout/qgslayout3dmapwidget.h
Expand Up @@ -28,8 +28,13 @@ class QgsLayout3DMapWidget : public QgsLayoutItemBaseWidget, private Ui::QgsLayo
public:
explicit QgsLayout3DMapWidget( QgsLayoutItem3DMap *map3D );

private slots:
void copy3DMapSettings();
void updateCameraPose();

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

#endif // QGSLAYOUT3DMAPWIDGET_H
21 changes: 14 additions & 7 deletions src/ui/layout/qgslayout3dmapwidgetbase.ui
Expand Up @@ -54,7 +54,7 @@
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<y>-65</y>
<width>510</width>
<height>635</height>
</rect>
Expand Down Expand Up @@ -90,7 +90,7 @@
</widget>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="mCenterXLineEdit">
<widget class="QgsDoubleSpinBox" name="mCenterXSpinBox">
<property name="decimals">
<number>1</number>
</property>
Expand All @@ -110,7 +110,7 @@
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="mCenterYLineEdit">
<widget class="QgsDoubleSpinBox" name="mCenterYSpinBox">
<property name="decimals">
<number>1</number>
</property>
Expand All @@ -130,7 +130,7 @@
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="mCenterZLineEdit">
<widget class="QgsDoubleSpinBox" name="mCenterZSpinBox">
<property name="decimals">
<number>1</number>
</property>
Expand All @@ -150,7 +150,7 @@
</widget>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="mDistanceToCenterLineEdit">
<widget class="QgsDoubleSpinBox" name="mDistanceToCenterSpinBox">
<property name="decimals">
<number>1</number>
</property>
Expand All @@ -167,7 +167,7 @@
</widget>
</item>
<item row="4" column="1">
<widget class="QDoubleSpinBox" name="mPitchAngleLineEdit">
<widget class="QgsDoubleSpinBox" name="mPitchAngleSpinBox">
<property name="suffix">
<string> °</string>
</property>
Expand All @@ -187,7 +187,7 @@
</widget>
</item>
<item row="5" column="1">
<widget class="QDoubleSpinBox" name="mHeadingAngleLineEdit">
<widget class="QgsDoubleSpinBox" name="mHeadingAngleSpinBox">
<property name="suffix">
<string> °</string>
</property>
Expand All @@ -208,6 +208,13 @@
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsDoubleSpinBox</class>
<extends>QDoubleSpinBox</extends>
<header>qgsdoublespinbox.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

0 comments on commit f08ebab

Please sign in to comment.