Add configuration widget for shapes

This commit is contained in:
Nyall Dawson 2017-10-17 07:04:54 +10:00
parent 7674bd746b
commit 2ec31d84d3
7 changed files with 427 additions and 3 deletions

View File

@ -60,6 +60,8 @@ class QgsLayoutItem : QgsLayoutObject, QGraphicsRectItem, QgsLayoutUndoObjectInt
UndoOpacity,
UndoSetId,
UndoRotation,
UndoShapeStyle,
UndoShapeCornerRadius,
};
explicit QgsLayoutItem( QgsLayout *layout, bool manageZValue = true );

View File

@ -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
@ -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

View File

@ -20,6 +20,7 @@
#include "qgslayoutviewrubberband.h"
#include "qgslayoutitemshape.h"
#include "qgslayoutmapwidget.h"
#include "qgslayoutshapewidget.h"
#include "qgslayoutitemmap.h"
void QgsLayoutAppUtils::registerGuiForKnownItemTypes()
@ -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 );

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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
};
/**

View File

@ -0,0 +1,179 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsLayoutShapeWidgetBase</class>
<widget class="QWidget" name="QgsLayoutShapeWidgetBase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>564</width>
<height>322</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">padding: 2px; font-weight: bold; background-color: rgb(200, 200, 200);</string>
</property>
<property name="text">
<string>Shape</string>
</property>
</widget>
</item>
<item>
<widget class="QgsScrollArea" name="scrollArea">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>548</width>
<height>285</height>
</rect>
</property>
<layout class="QVBoxLayout" name="mainLayout">
<item>
<widget class="QgsCollapsibleGroupBoxBasic" name="groupBox">
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="title">
<string>Main properties</string>
</property>
<property name="syncGroup" stdset="0">
<string notr="true">composeritem</string>
</property>
<property name="collapsed" stdset="0">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Corner radius</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QgsDoubleSpinBox" name="mCornerRadiusSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="suffix">
<string/>
</property>
<property name="maximum">
<double>999.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QgsLayoutUnitsComboBox" name="mRadiusUnitsComboBox"/>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Style</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QgsSymbolButton" name="mShapeStyleButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Change...</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QComboBox" name="mShapeComboBox"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsDoubleSpinBox</class>
<extends>QDoubleSpinBox</extends>
<header>qgsdoublespinbox.h</header>
</customwidget>
<customwidget>
<class>QgsScrollArea</class>
<extends>QScrollArea</extends>
<header>qgsscrollarea.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsCollapsibleGroupBoxBasic</class>
<extends>QGroupBox</extends>
<header>qgscollapsiblegroupbox.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsSymbolButton</class>
<extends>QToolButton</extends>
<header>qgssymbolbutton.h</header>
</customwidget>
<customwidget>
<class>QgsLayoutUnitsComboBox</class>
<extends>QComboBox</extends>
<header>qgslayoutunitscombobox.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>groupBox</tabstop>
<tabstop>scrollArea</tabstop>
<tabstop>mShapeComboBox</tabstop>
<tabstop>mCornerRadiusSpinBox</tabstop>
<tabstop>mRadiusUnitsComboBox</tabstop>
<tabstop>mShapeStyleButton</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>