Skip to content

Commit

Permalink
Add configuration widget for shapes
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Nov 7, 2017
1 parent 7674bd7 commit 2ec31d8
Show file tree
Hide file tree
Showing 7 changed files with 427 additions and 3 deletions.
2 changes: 2 additions & 0 deletions python/core/layout/qgslayoutitem.sip
Expand Up @@ -60,6 +60,8 @@ class QgsLayoutItem : QgsLayoutObject, QGraphicsRectItem, QgsLayoutUndoObjectInt
UndoOpacity,
UndoSetId,
UndoRotation,
UndoShapeStyle,
UndoShapeCornerRadius,
};

explicit QgsLayoutItem( QgsLayout *layout, bool manageZValue = true );
Expand Down
2 changes: 2 additions & 0 deletions src/app/CMakeLists.txt
Expand Up @@ -182,6 +182,7 @@ SET(QGIS_APP_SRCS
layout/qgslayoutmapwidget.cpp
layout/qgslayoutpagepropertieswidget.cpp
layout/qgslayoutpropertieswidget.cpp
layout/qgslayoutshapewidget.cpp

locator/qgsinbuiltlocatorfilters.cpp
locator/qgslocatoroptionswidget.cpp
Expand Down Expand Up @@ -379,6 +380,7 @@ SET (QGIS_APP_MOC_HDRS
layout/qgslayoutmapwidget.h
layout/qgslayoutpagepropertieswidget.h
layout/qgslayoutpropertieswidget.h
layout/qgslayoutshapewidget.h

locator/qgsinbuiltlocatorfilters.h
locator/qgslocatoroptionswidget.h
Expand Down
13 changes: 10 additions & 3 deletions src/app/layout/qgslayoutapputils.cpp
Expand Up @@ -20,6 +20,7 @@
#include "qgslayoutviewrubberband.h"
#include "qgslayoutitemshape.h"
#include "qgslayoutmapwidget.h"
#include "qgslayoutshapewidget.h"
#include "qgslayoutitemmap.h"

void QgsLayoutAppUtils::registerGuiForKnownItemTypes()
Expand Down Expand Up @@ -49,19 +50,25 @@ void QgsLayoutAppUtils::registerGuiForKnownItemTypes()
return new QgsLayoutMapWidget( qobject_cast< QgsLayoutItemMap * >( item ) );
}, createRubberBand ) );

registry->addLayoutItemGuiMetadata( new QgsLayoutItemGuiMetadata( QgsLayoutItemRegistry::LayoutShape, QObject::tr( "Rectangle" ), QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddBasicRectangle.svg" ) ), nullptr, createRubberBand, QStringLiteral( "shapes" ), 0, []( QgsLayout * layout )->QgsLayoutItem*
auto createShapeWidget =
[]( QgsLayoutItem * item )->QgsLayoutItemBaseWidget *
{
return new QgsLayoutShapeWidget( qobject_cast< QgsLayoutItemShape * >( item ) );
};

registry->addLayoutItemGuiMetadata( new QgsLayoutItemGuiMetadata( QgsLayoutItemRegistry::LayoutShape, QObject::tr( "Rectangle" ), QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddBasicRectangle.svg" ) ), createShapeWidget, createRubberBand, QStringLiteral( "shapes" ), 0, []( QgsLayout * layout )->QgsLayoutItem*
{
std::unique_ptr< QgsLayoutItemShape > shape = qgis::make_unique< QgsLayoutItemShape >( layout );
shape->setShapeType( QgsLayoutItemShape::Rectangle );
return shape.release();
} ) );
registry->addLayoutItemGuiMetadata( new QgsLayoutItemGuiMetadata( QgsLayoutItemRegistry::LayoutShape, QObject::tr( "Ellipse" ), QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddBasicCircle.svg" ) ), nullptr, createEllipseBand, QStringLiteral( "shapes" ), 0, []( QgsLayout * layout )->QgsLayoutItem*
registry->addLayoutItemGuiMetadata( new QgsLayoutItemGuiMetadata( QgsLayoutItemRegistry::LayoutShape, QObject::tr( "Ellipse" ), QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddBasicCircle.svg" ) ), createShapeWidget, createEllipseBand, QStringLiteral( "shapes" ), 0, []( QgsLayout * layout )->QgsLayoutItem*
{
std::unique_ptr< QgsLayoutItemShape > shape = qgis::make_unique< QgsLayoutItemShape >( layout );
shape->setShapeType( QgsLayoutItemShape::Ellipse );
return shape.release();
} ) );
registry->addLayoutItemGuiMetadata( new QgsLayoutItemGuiMetadata( QgsLayoutItemRegistry::LayoutShape, QObject::tr( "Triangle" ), QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddBasicTriangle.svg" ) ), nullptr, createTriangleBand, QStringLiteral( "shapes" ), 0, []( QgsLayout * layout )->QgsLayoutItem*
registry->addLayoutItemGuiMetadata( new QgsLayoutItemGuiMetadata( QgsLayoutItemRegistry::LayoutShape, QObject::tr( "Triangle" ), QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddBasicTriangle.svg" ) ), createShapeWidget, createTriangleBand, QStringLiteral( "shapes" ), 0, []( QgsLayout * layout )->QgsLayoutItem*
{
std::unique_ptr< QgsLayoutItemShape > shape = qgis::make_unique< QgsLayoutItemShape >( layout );
shape->setShapeType( QgsLayoutItemShape::Triangle );
Expand Down
172 changes: 172 additions & 0 deletions src/app/layout/qgslayoutshapewidget.cpp
@@ -0,0 +1,172 @@
/***************************************************************************
qgslayoutshapewidget.cpp
--------------------------
begin : November 2009
copyright : (C) 2009 by Marco Hugentobler
email : marco@hugis.net
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgslayoutshapewidget.h"
#include "qgsstyle.h"
#include "qgslayoutitemshape.h"
#include "qgslayout.h"
#include "qgslayoutundostack.h"

QgsLayoutShapeWidget::QgsLayoutShapeWidget( QgsLayoutItemShape *shape )
: QgsLayoutItemBaseWidget( nullptr, shape )
, mShape( shape )
{
setupUi( this );
connect( mShapeComboBox, static_cast<void ( QComboBox::* )( const QString & )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutShapeWidget::mShapeComboBox_currentIndexChanged );
connect( mCornerRadiusSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutShapeWidget::mCornerRadiusSpinBox_valueChanged );
setPanelTitle( tr( "Shape properties" ) );

//add widget for general composer item properties
mItemPropertiesWidget = new QgsLayoutItemPropertiesWidget( this, shape );
//shapes don't use background or frame, since the symbol style is set through a QgsSymbolSelectorWidget
mItemPropertiesWidget->showBackgroundGroup( false );
mItemPropertiesWidget->showFrameGroup( false );
mainLayout->addWidget( mItemPropertiesWidget );

blockAllSignals( true );

//shape types
mShapeComboBox->addItem( tr( "Rectangle" ), QgsLayoutItemShape::Rectangle );
mShapeComboBox->addItem( tr( "Ellipse" ), QgsLayoutItemShape::Ellipse );
mShapeComboBox->addItem( tr( "Triangle" ), QgsLayoutItemShape::Triangle );

mShapeStyleButton->setSymbolType( QgsSymbol::Fill );
mRadiusUnitsComboBox->linkToWidget( mCornerRadiusSpinBox );
mRadiusUnitsComboBox->setConverter( &mShape->layout()->context().measurementConverter() );

setGuiElementValues();

blockAllSignals( false );

if ( mShape )
{
connect( mShape, &QgsLayoutObject::changed, this, &QgsLayoutShapeWidget::setGuiElementValues );
mShapeStyleButton->registerExpressionContextGenerator( mShape );
}
connect( mShapeStyleButton, &QgsSymbolButton::changed, this, &QgsLayoutShapeWidget::symbolChanged );
connect( mRadiusUnitsComboBox, &QgsLayoutUnitsComboBox::changed, this, &QgsLayoutShapeWidget::radiusUnitsChanged );

#if 0 //TODO
mShapeStyleButton->setLayer( atlasCoverageLayer() );
#endif
}

bool QgsLayoutShapeWidget::setNewItem( QgsLayoutItem *item )
{
if ( item->type() != QgsLayoutItemRegistry::LayoutShape )
return false;

mShape = qobject_cast< QgsLayoutItemShape * >( item );
mItemPropertiesWidget->setItem( mShape );

setGuiElementValues();

return true;
}

void QgsLayoutShapeWidget::blockAllSignals( bool block )
{
mShapeComboBox->blockSignals( block );
mCornerRadiusSpinBox->blockSignals( block );
mRadiusUnitsComboBox->blockSignals( block );
mShapeStyleButton->blockSignals( block );
}

void QgsLayoutShapeWidget::setGuiElementValues()
{
if ( !mShape )
{
return;
}

blockAllSignals( true );

mShapeStyleButton->setSymbol( mShape->symbol()->clone() );

mCornerRadiusSpinBox->setValue( mShape->cornerRadius().length() );
mRadiusUnitsComboBox->setUnit( mShape->cornerRadius().units() );

mShapeComboBox->setCurrentIndex( mShapeComboBox->findData( mShape->shapeType() ) );
toggleRadiusSpin( mShape->shapeType() );

blockAllSignals( false );
}

void QgsLayoutShapeWidget::symbolChanged()
{
if ( !mShape )
return;

mShape->layout()->undoStack()->beginCommand( mShape, tr( "Change Shape Style" ), QgsLayoutItem::UndoShapeStyle );
mShape->setSymbol( mShapeStyleButton->clonedSymbol<QgsFillSymbol>() );
mShape->layout()->undoStack()->endCommand();
}

void QgsLayoutShapeWidget::mCornerRadiusSpinBox_valueChanged( double val )
{
if ( !mShape )
return;

mShape->layout()->undoStack()->beginCommand( mShape, tr( "Change Shape Radius" ), QgsLayoutItem::UndoShapeCornerRadius );
mShape->setCornerRadius( QgsLayoutMeasurement( val, mRadiusUnitsComboBox->unit() ) );
mShape->layout()->undoStack()->endCommand();
mShape->update();
}

void QgsLayoutShapeWidget::radiusUnitsChanged()
{
if ( !mShape )
return;

mShape->layout()->undoStack()->beginCommand( mShape, tr( "Change Shape Radius" ), QgsLayoutItem::UndoShapeCornerRadius );
mShape->setCornerRadius( QgsLayoutMeasurement( mCornerRadiusSpinBox->value(), mRadiusUnitsComboBox->unit() ) );
mShape->layout()->undoStack()->endCommand();
mShape->update();
}

void QgsLayoutShapeWidget::mShapeComboBox_currentIndexChanged( const QString & )
{
if ( !mShape )
{
return;
}

mShape->layout()->undoStack()->beginCommand( mShape, tr( "Change Shape Type" ) );
QgsLayoutItemShape::Shape shape = static_cast< QgsLayoutItemShape::Shape >( mShapeComboBox->currentData().toInt() );
mShape->setShapeType( shape );
toggleRadiusSpin( shape );
mShape->update();
mShape->layout()->undoStack()->endCommand();
}

void QgsLayoutShapeWidget::toggleRadiusSpin( QgsLayoutItemShape::Shape shape )
{
switch ( shape )
{
case QgsLayoutItemShape::Ellipse:
case QgsLayoutItemShape::Triangle:
{
mCornerRadiusSpinBox->setEnabled( false );
break;
}
case QgsLayoutItemShape::Rectangle:
{
mCornerRadiusSpinBox->setEnabled( true );
break;
}
}
}
60 changes: 60 additions & 0 deletions src/app/layout/qgslayoutshapewidget.h
@@ -0,0 +1,60 @@
/***************************************************************************
qgslayoutshapewidget.h
------------------------
begin : November 2009
copyright : (C) 2009 by Marco Hugentobler
email : marco@hugis.net
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSLAYOUTSHAPEWIDGET_H
#define QGSLAYOUTSHAPEWIDGET_H

#include "ui_qgslayoutshapewidgetbase.h"
#include "qgslayoutitemwidget.h"
#include "qgslayoutitemshape.h"

/**
* \ingroup app
* Input widget for the configuration of QgsLayoutItemShape
*/
class QgsLayoutShapeWidget: public QgsLayoutItemBaseWidget, private Ui::QgsLayoutShapeWidgetBase
{
Q_OBJECT
public:
explicit QgsLayoutShapeWidget( QgsLayoutItemShape *shape );

protected:

bool setNewItem( QgsLayoutItem *item ) override;


private:
QgsLayoutItemShape *mShape = nullptr;
QgsLayoutItemPropertiesWidget *mItemPropertiesWidget = nullptr;

//! Blocks / unblocks the signal of all GUI elements
void blockAllSignals( bool block );

private slots:
void mShapeComboBox_currentIndexChanged( const QString &text );
void mCornerRadiusSpinBox_valueChanged( double val );
void radiusUnitsChanged();
void symbolChanged();

//! Sets the GUI elements to the currentValues of mComposerShape
void setGuiElementValues();

//! Enables or disables the rounded radius spin box based on shape type
void toggleRadiusSpin( QgsLayoutItemShape::Shape shape );
};

#endif // QGSLAYOUTSHAPEWIDGET_H
2 changes: 2 additions & 0 deletions src/core/layout/qgslayoutitem.h
Expand Up @@ -93,6 +93,8 @@ class CORE_EXPORT QgsLayoutItem : public QgsLayoutObject, public QGraphicsRectIt
UndoOpacity, //!< Opacity adjustment
UndoSetId, //!< Change item ID
UndoRotation, //!< Rotation adjustment
UndoShapeStyle, //!< Shape symbol style
UndoShapeCornerRadius, //!< Shape corner radius
};

/**
Expand Down

0 comments on commit 2ec31d8

Please sign in to comment.