Merge pull request #4907 from nyalldawson/symbol_button

New QgsSymbolButton widget
This commit is contained in:
Nyall Dawson 2017-07-24 20:29:14 +10:00 committed by GitHub
commit d055def2d1
54 changed files with 1668 additions and 546 deletions

View File

@ -144,7 +144,7 @@ class QgsGradientColorRamp : QgsColorRamp
\param stops optional list of additional color stops
%End
static QgsColorRamp *create( const QgsStringMap &properties = QgsStringMap() );
static QgsColorRamp *create( const QgsStringMap &properties = QgsStringMap() ) /Factory/;
%Docstring
Creates a new QgsColorRamp from a map of properties
:rtype: QgsColorRamp
@ -477,7 +477,7 @@ class QgsPresetSchemeColorRamp : QgsColorRamp, QgsColorScheme
not available in Python bindings - use setColors instead
%End
static QgsColorRamp *create( const QgsStringMap &properties = QgsStringMap() );
static QgsColorRamp *create( const QgsStringMap &properties = QgsStringMap() ) /Factory/;
%Docstring
Returns a new QgsPresetSchemeColorRamp color ramp created using the properties encoded in a string
map.
@ -541,7 +541,7 @@ class QgsColorBrewerColorRamp : QgsColorRamp
\param inverted invert ramp ordering
%End
static QgsColorRamp *create( const QgsStringMap &properties = QgsStringMap() );
static QgsColorRamp *create( const QgsStringMap &properties = QgsStringMap() ) /Factory/;
%Docstring
Returns a new QgsColorBrewerColorRamp color ramp created using the properties encoded in a string
map.
@ -647,7 +647,7 @@ class QgsCptCityColorRamp : QgsGradientColorRamp
\param doLoadFile load cpt-city ramp from file
%End
static QgsColorRamp *create( const QgsStringMap &properties = QgsStringMap() );
static QgsColorRamp *create( const QgsStringMap &properties = QgsStringMap() ) /Factory/;
%Docstring
:rtype: QgsColorRamp
%End

View File

@ -88,7 +88,7 @@ return new default symbol for specified geometry type
:rtype: QgsSymbolLayer
%End
int symbolLayerCount();
int symbolLayerCount() const;
%Docstring
Returns total number of symbol layers contained in the symbol.
:return: count of symbol layers

View File

@ -231,8 +231,10 @@ class QgsSymbolLayer
virtual QgsSymbol *subSymbol();
%Docstring
Returns the symbol's sub symbol, if present.
:rtype: QgsSymbol
%End
virtual bool setSubSymbol( QgsSymbol *symbol /Transfer/ );
%Docstring
set layer's subsymbol. takes ownership of the passed symbol

View File

@ -52,7 +52,7 @@ Create a symbol layer of this type given the map of properties.
Create widget for symbol layer of this type. Can return NULL if there's no GUI
:rtype: QgsSymbolLayerWidget
%End
virtual QgsSymbolLayer *createSymbolLayerFromSld( QDomElement & );
virtual QgsSymbolLayer *createSymbolLayerFromSld( QDomElement & ) /Factory/;
%Docstring
Create a symbol layer of this type given the map of properties.
:rtype: QgsSymbolLayer
@ -85,9 +85,9 @@ Convenience metadata class that uses static functions to create symbol layer and
virtual QgsSymbolLayer *createSymbolLayer( const QgsStringMap &map );
virtual QgsSymbolLayerWidget *createSymbolLayerWidget( const QgsVectorLayer *vl );
virtual QgsSymbolLayer *createSymbolLayerFromSld( QDomElement &elem );
virtual QgsSymbolLayer *createSymbolLayer( const QgsStringMap &map ) /Factory/;
virtual QgsSymbolLayerWidget *createSymbolLayerWidget( const QgsVectorLayer *vl ) /Factory/;
virtual QgsSymbolLayer *createSymbolLayerFromSld( QDomElement &elem ) /Factory/;
virtual void resolvePaths( QgsStringMap &properties, const QgsPathResolver &pathResolver, bool saving );
protected:
@ -133,7 +133,7 @@ create a new instance of symbol layer given symbol layer name and properties
:rtype: QgsSymbolLayer
%End
QgsSymbolLayer *createSymbolLayerFromSld( const QString &name, QDomElement &element ) const;
QgsSymbolLayer *createSymbolLayerFromSld( const QString &name, QDomElement &element ) const /Factory/;
%Docstring
create a new instance of symbol layer given symbol layer name and SLD
:rtype: QgsSymbolLayer

View File

@ -337,15 +337,15 @@ Writes a symbol definition to XML
:rtype: bool
%End
static QgsSymbolLayer *createFillLayerFromSld( QDomElement &element );
static QgsSymbolLayer *createFillLayerFromSld( QDomElement &element ) /Factory/;
%Docstring
:rtype: QgsSymbolLayer
%End
static QgsSymbolLayer *createLineLayerFromSld( QDomElement &element );
static QgsSymbolLayer *createLineLayerFromSld( QDomElement &element ) /Factory/;
%Docstring
:rtype: QgsSymbolLayer
%End
static QgsSymbolLayer *createMarkerLayerFromSld( QDomElement &element );
static QgsSymbolLayer *createMarkerLayerFromSld( QDomElement &element ) /Factory/;
%Docstring
:rtype: QgsSymbolLayer
%End
@ -548,6 +548,25 @@ Writes a collection of symbols to XML with specified tagName for the top-level e
static void clearSymbolMap( QgsSymbolMap &symbols );
static QMimeData *symbolToMimeData( QgsSymbol *symbol ) /Factory/;
%Docstring
Creates new mime data from a ``symbol``.
This also sets the mime color data to match the symbol's color, so that copied symbols
can be paste in places where a color is expected.
.. seealso:: symbolFromMimeData()
.. versionadded:: 3.0
:rtype: QMimeData
%End
static QgsSymbol *symbolFromMimeData( const QMimeData *data ) /Factory/;
%Docstring
Attempts to parse ``mime`` data as a symbol. A new symbol instance will be returned
if the data was successfully converted to a symbol.
.. seealso:: symbolToMimeData()
.. versionadded:: 3.0
:rtype: QgsSymbol
%End
static QgsColorRamp *loadColorRamp( QDomElement &element ) /Factory/;
%Docstring
Creates a color ramp from the settings encoded in an XML element
@ -577,7 +596,7 @@ Writes a collection of symbols to XML with specified tagName for the top-level e
:rtype: QVariant
%End
static QgsColorRamp *loadColorRamp( const QVariant &value );
static QgsColorRamp *loadColorRamp( const QVariant &value ) /Factory/;
%Docstring
Load a color ramp from a QVariantMap, wrapped in a QVariant.
You can use QgsXmlUtils.readVariant to load it from an XML document.
@ -605,7 +624,7 @@ Writes a collection of symbols to XML with specified tagName for the top-level e
:rtype: list of QColor
%End
static QMimeData *colorToMimeData( const QColor &color );
static QMimeData *colorToMimeData( const QColor &color ) /Factory/;
%Docstring
Creates mime data from a color. Sets both the mime data's color data, and the
mime data's text with the color's hex code.
@ -636,7 +655,7 @@ Writes a collection of symbols to XML with specified tagName for the top-level e
:rtype: QgsNamedColorList
%End
static QMimeData *colorListToMimeData( const QgsNamedColorList &colorList, const bool allFormats = true );
static QMimeData *colorListToMimeData( const QgsNamedColorList &colorList, const bool allFormats = true ) /Factory/;
%Docstring
Creates mime data from a list of named colors
\param colorList list of named colors

View File

@ -188,6 +188,7 @@
%Include qgsstatusbar.sip
%Include qgssublayersdialog.sip
%Include qgssubstitutionlistwidget.sip
%Include qgssymbolbutton.sip
%Include qgstablewidgetbase.sip
%Include qgstabwidget.sip
%Include qgstaskmanagerwidget.sip

View File

@ -0,0 +1,188 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgssymbolbutton.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsSymbolButton : QToolButton
{
%Docstring
A button for creating and modifying QgsSymbol settings.
The button shows a preview icon for the current symbol, and will open a detailed symbol editor dialog (or
panel widget) when clicked.
.. versionadded:: 3.0
%End
%TypeHeaderCode
#include "qgssymbolbutton.h"
%End
public:
QgsSymbolButton( QWidget *parent /TransferThis/ = 0, const QString &dialogTitle = QString() );
%Docstring
Construct a new symbol button.
Use ``dialogTitle`` string to define the title to show in the symbol settings dialog.
%End
virtual QSize minimumSizeHint() const;
void setSymbolType( QgsSymbol::SymbolType type );
%Docstring
Sets the symbol ``type`` which the button requires.
If the type differs from the current symbol type, the symbol will be reset
to a default symbol style of the new type.
.. seealso:: symbolType()
%End
QgsSymbol::SymbolType symbolType() const;
%Docstring
Returns the symbol type which the button requires.
.. seealso:: setSymbolType()
:rtype: QgsSymbol.SymbolType
%End
void setDialogTitle( const QString &title );
%Docstring
Sets the ``title`` for the symbol settings dialog window.
.. seealso:: dialogTitle()
%End
QString dialogTitle() const;
%Docstring
Returns the title for the symbol settings dialog window.
.. seealso:: setDialogTitle()
:rtype: str
%End
QgsSymbol *symbol();
%Docstring
Returns the current symbol defined by the button.
.. seealso:: setSymbol()
.. seealso:: changed()
:rtype: QgsSymbol
%End
QgsMapCanvas *mapCanvas() const;
%Docstring
Returns the map canvas associated with the widget.
.. seealso:: setMapCanvas()
:rtype: QgsMapCanvas
%End
void setMapCanvas( QgsMapCanvas *canvas );
%Docstring
Sets a map ``canvas`` to associate with the widget. This allows the
widget to fetch current settings from the map canvas, such as current scale.
.. seealso:: mapCanvas()
%End
QgsVectorLayer *layer() const;
%Docstring
Returns the layer associated with the widget.
.. seealso:: setLayer()
:rtype: QgsVectorLayer
%End
void setLayer( QgsVectorLayer *layer );
%Docstring
Sets a ``layer`` to associate with the widget. This allows the
widget to setup layer related settings within the symbol settings dialog,
such as correctly populating data defined override buttons.
.. seealso:: layer()
%End
void registerExpressionContextGenerator( QgsExpressionContextGenerator *generator );
%Docstring
Register an expression context generator class that will be used to retrieve
an expression context for the button when required.
%End
public slots:
void setSymbol( QgsSymbol *symbol /Transfer/ );
%Docstring
Sets the ``symbol`` for the button. Ownership of ``symbol`` is transferred to the
button.
.. seealso:: symbol()
.. seealso:: changed()
%End
void setColor( const QColor &color );
%Docstring
Sets the current ``color`` for the symbol. Will emit a changed() signal if the color is different
to the previous symbol color.
%End
void copySymbol();
%Docstring
Copies the current symbol to the clipboard.
.. seealso:: pasteSymbol()
%End
void pasteSymbol();
%Docstring
Pastes a symbol from the clipboard. If clipboard does not contain a valid
symbol then no change is applied.
.. seealso:: copySymbol()
%End
void copyColor();
%Docstring
Copies the current symbol color to the clipboard.
.. seealso:: pasteColor()
%End
void pasteColor();
%Docstring
Pastes a color from the clipboard to the symbol. If clipboard does not contain a valid
color or string representation of a color, then no change is applied.
.. seealso:: copyColor()
%End
signals:
void changed();
%Docstring
Emitted when the symbol's settings are changed.
.. seealso:: symbol()
.. seealso:: setSymbol()
%End
protected:
virtual void changeEvent( QEvent *e );
virtual void showEvent( QShowEvent *e );
virtual void resizeEvent( QResizeEvent *event );
virtual void mousePressEvent( QMouseEvent *e );
virtual void mouseMoveEvent( QMouseEvent *e );
virtual void dragEnterEvent( QDragEnterEvent *e );
virtual void dragLeaveEvent( QDragLeaveEvent *e );
virtual void dropEvent( QDropEvent *e );
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgssymbolbutton.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -11,7 +11,7 @@
class QgsPointClusterRendererWidget: QgsRendererWidget
class QgsPointClusterRendererWidget: QgsRendererWidget, QgsExpressionContextGenerator
{
%Docstring
A widget which allows configuration of the properties for a QgsPointClusterRenderer.
@ -48,6 +48,9 @@ class QgsPointClusterRendererWidget: QgsRendererWidget
virtual void setContext( const QgsSymbolWidgetContext &context );
virtual QgsExpressionContext createExpressionContext() const;
};
/************************************************************************

View File

@ -10,7 +10,7 @@
class QgsPointDisplacementRendererWidget: QgsRendererWidget
class QgsPointDisplacementRendererWidget: QgsRendererWidget, QgsExpressionContextGenerator
{
%TypeHeaderCode
@ -29,6 +29,9 @@ class QgsPointDisplacementRendererWidget: QgsRendererWidget
virtual void setContext( const QgsSymbolWidgetContext &context );
virtual QgsExpressionContext createExpressionContext() const;
};
/************************************************************************

View File

@ -45,6 +45,8 @@ QgsComposerShapeWidget::QgsComposerShapeWidget( QgsComposerShape *composerShape
mShapeComboBox->addItem( tr( "Rectangle" ) );
mShapeComboBox->addItem( tr( "Triangle" ) );
mShapeStyleButton->setSymbolType( QgsSymbol::Fill );
setGuiElementValues();
blockAllSignals( false );
@ -52,7 +54,10 @@ QgsComposerShapeWidget::QgsComposerShapeWidget( QgsComposerShape *composerShape
if ( mComposerShape )
{
connect( mComposerShape, &QgsComposerObject::itemChanged, this, &QgsComposerShapeWidget::setGuiElementValues );
mShapeStyleButton->registerExpressionContextGenerator( mComposerShape );
}
connect( mShapeStyleButton, &QgsSymbolButton::changed, this, &QgsComposerShapeWidget::symbolChanged );
mShapeStyleButton->setLayer( atlasCoverageLayer() );
}
QgsComposerShapeWidget::~QgsComposerShapeWidget()
@ -76,7 +81,7 @@ void QgsComposerShapeWidget::setGuiElementValues()
blockAllSignals( true );
updateShapeStyle();
mShapeStyleButton->setSymbol( mComposerShape->shapeStyleSymbol()->clone() );
mCornerRadiusSpinBox->setValue( mComposerShape->cornerRadius() );
if ( mComposerShape->shapeType() == QgsComposerShape::Ellipse )
@ -98,38 +103,16 @@ void QgsComposerShapeWidget::setGuiElementValues()
blockAllSignals( false );
}
void QgsComposerShapeWidget::on_mShapeStyleButton_clicked()
void QgsComposerShapeWidget::symbolChanged()
{
if ( !mComposerShape )
{
return;
}
// use the atlas coverage layer, if any
QgsVectorLayer *coverageLayer = atlasCoverageLayer();
QgsFillSymbol *newSymbol = mComposerShape->shapeStyleSymbol()->clone();
QgsExpressionContext context = mComposerShape->createExpressionContext();
QgsSymbolSelectorWidget *d = new QgsSymbolSelectorWidget( newSymbol, QgsStyle::defaultStyle(), coverageLayer, nullptr );
QgsSymbolWidgetContext symbolContext;
symbolContext.setExpressionContext( &context );
d->setContext( symbolContext );
connect( d, &QgsPanelWidget::widgetChanged, this, &QgsComposerShapeWidget::updateSymbolFromWidget );
connect( d, &QgsPanelWidget::panelAccepted, this, &QgsComposerShapeWidget::cleanUpSymbolSelector );
openPanel( d );
mComposerShape->beginCommand( tr( "Shape style changed" ) );
}
void QgsComposerShapeWidget::updateShapeStyle()
{
if ( mComposerShape )
{
mComposerShape->refreshSymbol();
QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mComposerShape->shapeStyleSymbol(), mShapeStyleButton->iconSize() );
mShapeStyleButton->setIcon( icon );
}
mComposerShape->setShapeStyleSymbol( mShapeStyleButton->clonedSymbol<QgsFillSymbol>() );
mComposerShape->endCommand();
}
void QgsComposerShapeWidget::on_mCornerRadiusSpinBox_valueChanged( double val )
@ -179,23 +162,3 @@ void QgsComposerShapeWidget::toggleRadiusSpin( const QString &shapeText )
mCornerRadiusSpinBox->setEnabled( false );
}
}
void QgsComposerShapeWidget::updateSymbolFromWidget()
{
if ( QgsSymbolSelectorWidget *w = qobject_cast<QgsSymbolSelectorWidget *>( sender() ) )
mComposerShape->setShapeStyleSymbol( static_cast< QgsFillSymbol * >( w->symbol() ) );
}
void QgsComposerShapeWidget::cleanUpSymbolSelector( QgsPanelWidget *container )
{
QgsSymbolSelectorWidget *w = qobject_cast<QgsSymbolSelectorWidget *>( container );
if ( !w )
return;
delete w->symbol();
updateShapeStyle();
mComposerShape->endCommand();
}

View File

@ -40,17 +40,13 @@ class QgsComposerShapeWidget: public QgsComposerItemBaseWidget, private Ui::QgsC
private slots:
void on_mShapeComboBox_currentIndexChanged( const QString &text );
void on_mCornerRadiusSpinBox_valueChanged( double val );
void on_mShapeStyleButton_clicked();
void symbolChanged();
//! Sets the GUI elements to the currentValues of mComposerShape
void setGuiElementValues();
void updateShapeStyle();
//! Enables or disables the rounded radius spin box based on shape type
void toggleRadiusSpin( const QString &shapeText );
void updateSymbolFromWidget();
void cleanUpSymbolSelector( QgsPanelWidget *container );
};
#endif // QGSCOMPOSERSHAPEWIDGET_H

View File

@ -22,17 +22,20 @@
#include "qgssymbollayerutils.h"
#include "qgssymbol.h"
#include "qgssymbolselectordialog.h"
#include "qgisapp.h"
#include <QColorDialog>
QgsAnnotationWidget::QgsAnnotationWidget( QgsMapCanvasAnnotationItem *item, QWidget *parent, Qt::WindowFlags f )
: QWidget( parent, f )
, mItem( item )
, mMarkerSymbol( nullptr )
{
setupUi( this );
mLayerComboBox->setAllowEmptyLayer( true );
mMapMarkerButton->setSymbolType( QgsSymbol::Marker );
mFrameStyleButton->setSymbolType( QgsSymbol::Fill );
if ( mItem && mItem->annotation() )
{
QgsAnnotation *annotation = mItem->annotation();
@ -57,18 +60,18 @@ QgsAnnotationWidget::QgsAnnotationWidget( QgsMapCanvasAnnotationItem *item, QWid
const QgsMarkerSymbol *symbol = annotation->markerSymbol();
if ( symbol )
{
mMarkerSymbol.reset( symbol->clone() );
updateCenterIcon();
mMapMarkerButton->setSymbol( symbol->clone() );
}
const QgsFillSymbol *fill = annotation->fillSymbol();
if ( fill )
{
mFillSymbol.reset( fill->clone() );
updateFillIcon();
mFrameStyleButton->setSymbol( fill->clone() );
}
blockAllSignals( false );
}
mMapMarkerButton->setMapCanvas( QgisApp::instance()->mapCanvas() );
mFrameStyleButton->setMapCanvas( QgisApp::instance()->mapCanvas() );
}
QgsAnnotationWidget::~QgsAnnotationWidget()
@ -83,8 +86,8 @@ void QgsAnnotationWidget::apply()
if ( annotation )
{
annotation->setHasFixedMapPosition( mMapPositionFixedCheckBox->checkState() == Qt::Checked );
annotation->setFillSymbol( mFillSymbol->clone() );
annotation->setMarkerSymbol( mMarkerSymbol->clone() );
annotation->setFillSymbol( mFrameStyleButton->clonedSymbol<QgsFillSymbol>() );
annotation->setMarkerSymbol( mMapMarkerButton->clonedSymbol<QgsMarkerSymbol>() );
annotation->setMapLayer( mLayerComboBox->currentLayer() );
annotation->setContentsMargin( QgsMargins( mSpinLeftMargin->value(),
mSpinTopMargin->value(),
@ -101,63 +104,3 @@ void QgsAnnotationWidget::blockAllSignals( bool block )
mMapMarkerButton->blockSignals( block );
mLayerComboBox->blockSignals( block );
}
void QgsAnnotationWidget::on_mMapMarkerButton_clicked()
{
if ( !mMarkerSymbol )
{
return;
}
QgsMarkerSymbol *markerSymbol = mMarkerSymbol->clone();
QgsSymbolSelectorDialog dlg( markerSymbol, QgsStyle::defaultStyle(), nullptr, this );
if ( dlg.exec() == QDialog::Rejected )
{
delete markerSymbol;
}
else
{
mMarkerSymbol.reset( markerSymbol );
updateCenterIcon();
}
}
void QgsAnnotationWidget::on_mFrameStyleButton_clicked()
{
if ( !mFillSymbol )
{
return;
}
QgsFillSymbol *fillSymbol = mFillSymbol->clone();
QgsSymbolSelectorDialog dlg( fillSymbol, QgsStyle::defaultStyle(), nullptr, this );
if ( dlg.exec() == QDialog::Rejected )
{
delete fillSymbol;
}
else
{
mFillSymbol.reset( fillSymbol );
updateFillIcon();
backgroundColorChanged( fillSymbol->color() );
}
}
void QgsAnnotationWidget::updateCenterIcon()
{
if ( !mMarkerSymbol )
{
return;
}
QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mMarkerSymbol.get(), mMapMarkerButton->iconSize() );
mMapMarkerButton->setIcon( icon );
}
void QgsAnnotationWidget::updateFillIcon()
{
if ( !mFillSymbol )
{
return;
}
QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mFillSymbol.get(), mFrameStyleButton->iconSize() );
mFrameStyleButton->setIcon( icon );
}

View File

@ -42,14 +42,8 @@ class APP_EXPORT QgsAnnotationWidget: public QWidget, private Ui::QgsAnnotationW
//! Emitted when the background color of the annotation is changed
void backgroundColorChanged( const QColor &color );
private slots:
void on_mMapMarkerButton_clicked();
void on_mFrameStyleButton_clicked();
private:
QgsMapCanvasAnnotationItem *mItem = nullptr;
std::unique_ptr< QgsMarkerSymbol > mMarkerSymbol;
std::unique_ptr< QgsFillSymbol > mFillSymbol;
void blockAllSignals( bool block );
void updateCenterIcon();

View File

@ -31,11 +31,12 @@
QgsDecorationGridDialog::QgsDecorationGridDialog( QgsDecorationGrid &deco, QWidget *parent )
: QDialog( parent )
, mDeco( deco )
, mLineSymbol( nullptr )
, mMarkerSymbol( nullptr )
{
setupUi( this );
mMarkerSymbolButton->setSymbolType( QgsSymbol::Marker );
mLineSymbolButton->setSymbolType( QgsSymbol::Line );
mAnnotationFontButton->setMode( QgsFontButton::ModeQFont );
QgsSettings settings;
@ -65,6 +66,9 @@ QgsDecorationGridDialog::QgsDecorationGridDialog( QgsDecorationGrid &deco, QWidg
connect( buttonBox->button( QDialogButtonBox::Apply ), &QAbstractButton::clicked, this, &QgsDecorationGridDialog::apply );
connect( mAnnotationFontButton, &QgsFontButton::changed, this, &QgsDecorationGridDialog::annotationFontChanged );
mMarkerSymbolButton->setMapCanvas( QgisApp::instance()->mapCanvas() );
mLineSymbolButton->setMapCanvas( QgisApp::instance()->mapCanvas() );
}
void QgsDecorationGridDialog::updateGuiElements()
@ -88,22 +92,8 @@ void QgsDecorationGridDialog::updateGuiElements()
// mLineWidthSpinBox->setValue( gridPen.widthF() );
// mLineColorButton->setColor( gridPen.color() );
if ( mLineSymbol )
delete mLineSymbol;
if ( mDeco.lineSymbol() )
{
mLineSymbol = static_cast<QgsLineSymbol *>( mDeco.lineSymbol()->clone() );
QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mLineSymbol, mLineSymbolButton->iconSize() );
mLineSymbolButton->setIcon( icon );
}
if ( mMarkerSymbol )
delete mMarkerSymbol;
if ( mDeco.markerSymbol() )
{
mMarkerSymbol = static_cast<QgsMarkerSymbol *>( mDeco.markerSymbol()->clone() );
QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mMarkerSymbol, mMarkerSymbolButton->iconSize() );
mMarkerSymbolButton->setIcon( icon );
}
mLineSymbolButton->setSymbol( mDeco.lineSymbol()->clone() );
mMarkerSymbolButton->setSymbol( mDeco.markerSymbol()->clone() );
whileBlocking( mAnnotationFontButton )->setCurrentFont( mDeco.gridAnnotationFont() );
@ -157,26 +147,14 @@ void QgsDecorationGridDialog::updateDecoFromGui()
mDeco.setGridAnnotationDirection( QgsDecorationGrid::BoundaryDirection );
}
mDeco.setGridAnnotationPrecision( mCoordinatePrecisionSpinBox->value() );
if ( mLineSymbol )
{
mDeco.setLineSymbol( mLineSymbol );
mLineSymbol = mDeco.lineSymbol()->clone();
}
if ( mMarkerSymbol )
{
mDeco.setMarkerSymbol( mMarkerSymbol );
mMarkerSymbol = mDeco.markerSymbol()->clone();
}
mDeco.setLineSymbol( mLineSymbolButton->clonedSymbol< QgsLineSymbol >() );
mDeco.setMarkerSymbol( mMarkerSymbolButton->clonedSymbol< QgsMarkerSymbol >() );
}
QgsDecorationGridDialog::~QgsDecorationGridDialog()
{
QgsSettings settings;
settings.setValue( QStringLiteral( "/Windows/DecorationGrid/geometry" ), saveGeometry() );
if ( mLineSymbol )
delete mLineSymbol;
if ( mMarkerSymbol )
delete mMarkerSymbol;
}
void QgsDecorationGridDialog::on_buttonBox_helpRequested()
@ -210,53 +188,6 @@ void QgsDecorationGridDialog::on_mGridTypeComboBox_currentIndexChanged( int inde
mMarkerSymbolButton->setEnabled( index == QgsDecorationGrid::Marker );
}
void QgsDecorationGridDialog::on_mLineSymbolButton_clicked()
{
if ( ! mLineSymbol )
return;
QgsLineSymbol *lineSymbol = mLineSymbol->clone();
QgsSymbolSelectorDialog dlg( lineSymbol, QgsStyle::defaultStyle(), nullptr, this );
if ( dlg.exec() == QDialog::Rejected )
{
delete lineSymbol;
}
else
{
delete mLineSymbol;
mLineSymbol = lineSymbol;
if ( mLineSymbol )
{
QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mLineSymbol, mLineSymbolButton->iconSize() );
mLineSymbolButton->setIcon( icon );
}
}
}
void QgsDecorationGridDialog::on_mMarkerSymbolButton_clicked()
{
if ( ! mMarkerSymbol )
return;
QgsMarkerSymbol *markerSymbol = mMarkerSymbol->clone();
QgsSymbolSelectorDialog dlg( markerSymbol, QgsStyle::defaultStyle(), nullptr, this );
if ( dlg.exec() == QDialog::Rejected )
{
delete markerSymbol;
}
else
{
delete mMarkerSymbol;
mMarkerSymbol = markerSymbol;
if ( mMarkerSymbol )
{
QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mMarkerSymbol, mMarkerSymbolButton->iconSize() );
mMarkerSymbolButton->setIcon( icon );
}
}
}
void QgsDecorationGridDialog::on_mPbtnUpdateFromExtents_clicked()
{
updateInterval( true );

View File

@ -40,8 +40,6 @@ class APP_EXPORT QgsDecorationGridDialog : public QDialog, private Ui::QgsDecora
void on_buttonBox_rejected();
void on_buttonBox_helpRequested();
void on_mGridTypeComboBox_currentIndexChanged( int index );
void on_mLineSymbolButton_clicked();
void on_mMarkerSymbolButton_clicked();
void on_mPbtnUpdateFromExtents_clicked();
void on_mPbtnUpdateFromLayer_clicked();
@ -51,8 +49,6 @@ class APP_EXPORT QgsDecorationGridDialog : public QDialog, private Ui::QgsDecora
private:
QgsDecorationGrid &mDeco;
QgsLineSymbol *mLineSymbol = nullptr;
QgsMarkerSymbol *mMarkerSymbol = nullptr;
void updateGuiElements();
void updateDecoFromGui();

View File

@ -35,6 +35,8 @@ QgsDecorationLayoutExtentDialog::QgsDecorationLayoutExtentDialog( QgsDecorationL
{
setupUi( this );
mSymbolButton->setSymbolType( QgsSymbol::Fill );
QgsSettings settings;
restoreGeometry( settings.value( "/Windows/DecorationLayoutExtent/geometry" ).toByteArray() );
@ -44,19 +46,14 @@ QgsDecorationLayoutExtentDialog::QgsDecorationLayoutExtentDialog( QgsDecorationL
updateGuiElements();
connect( buttonBox->button( QDialogButtonBox::Apply ), &QAbstractButton::clicked, this, &QgsDecorationLayoutExtentDialog::apply );
connect( mSymbolButton, &QPushButton::clicked, this, &QgsDecorationLayoutExtentDialog::changeSymbol );
mSymbolButton->setMapCanvas( QgisApp::instance()->mapCanvas() );
}
void QgsDecorationLayoutExtentDialog::updateGuiElements()
{
grpEnable->setChecked( mDeco.enabled() );
if ( mDeco.symbol() )
{
mSymbol.reset( static_cast<QgsFillSymbol *>( mDeco.symbol()->clone() ) );
QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mSymbol.get(), mSymbolButton->iconSize() );
mSymbolButton->setIcon( icon );
}
mSymbolButton->setSymbol( mDeco.symbol()->clone() );
mButtonFontStyle->setTextFormat( mDeco.textFormat() );
mCheckBoxLabelExtents->setChecked( mDeco.labelExtents() );
}
@ -64,11 +61,7 @@ void QgsDecorationLayoutExtentDialog::updateGuiElements()
void QgsDecorationLayoutExtentDialog::updateDecoFromGui()
{
mDeco.setEnabled( grpEnable->isChecked() );
if ( mSymbol )
{
mDeco.setSymbol( mSymbol->clone() );
}
mDeco.setSymbol( mSymbolButton->clonedSymbol< QgsFillSymbol >() );
mDeco.setTextFormat( mButtonFontStyle->textFormat() );
mDeco.setLabelExtents( mCheckBoxLabelExtents->isChecked() );
}
@ -95,25 +88,3 @@ void QgsDecorationLayoutExtentDialog::on_buttonBox_rejected()
{
reject();
}
void QgsDecorationLayoutExtentDialog::changeSymbol()
{
if ( !mSymbol )
return;
QgsFillSymbol *symbol = mSymbol->clone();
QgsSymbolSelectorDialog dlg( symbol, QgsStyle::defaultStyle(), nullptr, this );
if ( dlg.exec() == QDialog::Rejected )
{
delete symbol;
}
else
{
mSymbol.reset( symbol );
if ( mSymbol )
{
QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mSymbol.get(), mSymbolButton->iconSize() );
mSymbolButton->setIcon( icon );
}
}
}

View File

@ -39,11 +39,9 @@ class APP_EXPORT QgsDecorationLayoutExtentDialog : public QDialog, private Ui::Q
void on_buttonBox_accepted();
void on_buttonBox_rejected();
void changeSymbol();
private:
QgsDecorationLayoutExtent &mDeco;
std::unique_ptr< QgsFillSymbol > mSymbol;
void updateGuiElements();
void updateDecoFromGui();

View File

@ -22,6 +22,7 @@
#include <QFileDialog>
#include <QFileInfo>
#include <QGraphicsScene>
#include <QPushButton>
QgsFormAnnotationDialog::QgsFormAnnotationDialog( QgsMapCanvasAnnotationItem *item, QWidget *parent, Qt::WindowFlags f )
: QDialog( parent, f )

View File

@ -22,6 +22,7 @@
#include <QFileDialog>
#include <QFileInfo>
#include <QGraphicsScene>
#include <QPushButton>
QgsHtmlAnnotationDialog::QgsHtmlAnnotationDialog( QgsMapCanvasAnnotationItem *item, QWidget *parent, Qt::WindowFlags f )
: QDialog( parent, f )

View File

@ -24,6 +24,7 @@
#include <QFileDialog>
#include <QFileInfo>
#include <QGraphicsScene>
#include <QPushButton>
QgsSvgAnnotationDialog::QgsSvgAnnotationDialog( QgsMapCanvasAnnotationItem *item, QWidget *parent, Qt::WindowFlags f )
: QDialog( parent, f )

View File

@ -142,7 +142,7 @@ class CORE_EXPORT QgsGradientColorRamp : public QgsColorRamp
const QgsGradientStopsList &stops = QgsGradientStopsList() );
//! Creates a new QgsColorRamp from a map of properties
static QgsColorRamp *create( const QgsStringMap &properties = QgsStringMap() );
static QgsColorRamp *create( const QgsStringMap &properties = QgsStringMap() ) SIP_FACTORY;
virtual int count() const override { return mStops.count() + 2; }
virtual double value( int index ) const override;
@ -439,7 +439,7 @@ class CORE_EXPORT QgsPresetSchemeColorRamp : public QgsColorRamp, public QgsColo
* \param properties color ramp properties
* \see properties()
*/
static QgsColorRamp *create( const QgsStringMap &properties = QgsStringMap() );
static QgsColorRamp *create( const QgsStringMap &properties = QgsStringMap() ) SIP_FACTORY;
/** Sets the list of colors used by the ramp.
* \param colors list of colors
@ -496,7 +496,7 @@ class CORE_EXPORT QgsColorBrewerColorRamp : public QgsColorRamp
* \param properties color ramp properties
* \see properties()
*/
static QgsColorRamp *create( const QgsStringMap &properties = QgsStringMap() );
static QgsColorRamp *create( const QgsStringMap &properties = QgsStringMap() ) SIP_FACTORY;
virtual double value( int index ) const override;
virtual QColor color( double value ) const override;
@ -586,7 +586,7 @@ class CORE_EXPORT QgsCptCityColorRamp : public QgsGradientColorRamp
const QString &variantName = QString(), bool inverted = false,
bool doLoadFile = true );
static QgsColorRamp *create( const QgsStringMap &properties = QgsStringMap() );
static QgsColorRamp *create( const QgsStringMap &properties = QgsStringMap() ) SIP_FACTORY;
virtual QString type() const override { return QStringLiteral( "cpt-city" ); }

0
src/core/qgsunittypes.cpp Executable file → Normal file
View File

View File

@ -136,7 +136,7 @@ class CORE_EXPORT QgsSymbol
* \see symbolLayers
* \see symbolLayer
*/
int symbolLayerCount() { return mLayers.count(); }
int symbolLayerCount() const { return mLayers.count(); }
/**
* Insert symbol layer to specified index

View File

@ -252,7 +252,11 @@ class CORE_EXPORT QgsSymbolLayer
virtual void drawPreviewIcon( QgsSymbolRenderContext &context, QSize size ) = 0;
/**
* Returns the symbol's sub symbol, if present.
*/
virtual QgsSymbol *subSymbol() { return nullptr; }
//! set layer's subsymbol. takes ownership of the passed symbol
virtual bool setSubSymbol( QgsSymbol *symbol SIP_TRANSFER ) { delete symbol; return false; }

View File

@ -50,7 +50,7 @@ class CORE_EXPORT QgsSymbolLayerAbstractMetadata
//! Create widget for symbol layer of this type. Can return NULL if there's no GUI
virtual QgsSymbolLayerWidget *createSymbolLayerWidget( const QgsVectorLayer * ) SIP_FACTORY { return nullptr; }
//! Create a symbol layer of this type given the map of properties.
virtual QgsSymbolLayer *createSymbolLayerFromSld( QDomElement & ) { return nullptr; }
virtual QgsSymbolLayer *createSymbolLayerFromSld( QDomElement & ) SIP_FACTORY { return nullptr; }
/** Resolve paths in symbol layer's properties (if there are any paths).
* When saving is true, paths are converted from absolute to relative,
@ -109,9 +109,9 @@ class CORE_EXPORT QgsSymbolLayerMetadata : public QgsSymbolLayerAbstractMetadata
//! \note not available in Python bindings
void setWidgetFunction( QgsSymbolLayerWidgetFunc f ) { mWidgetFunc = f; } SIP_SKIP
virtual QgsSymbolLayer *createSymbolLayer( const QgsStringMap &map ) override { return mCreateFunc ? mCreateFunc( map ) : nullptr; } SIP_FACTORY
virtual QgsSymbolLayerWidget *createSymbolLayerWidget( const QgsVectorLayer *vl ) override { return mWidgetFunc ? mWidgetFunc( vl ) : nullptr; } SIP_FACTORY
virtual QgsSymbolLayer *createSymbolLayerFromSld( QDomElement &elem ) override { return mCreateFromSldFunc ? mCreateFromSldFunc( elem ) : nullptr; } SIP_FACTORY
virtual QgsSymbolLayer *createSymbolLayer( const QgsStringMap &map ) override SIP_FACTORY { return mCreateFunc ? mCreateFunc( map ) : nullptr; }
virtual QgsSymbolLayerWidget *createSymbolLayerWidget( const QgsVectorLayer *vl ) override SIP_FACTORY { return mWidgetFunc ? mWidgetFunc( vl ) : nullptr; }
virtual QgsSymbolLayer *createSymbolLayerFromSld( QDomElement &elem ) override SIP_FACTORY { return mCreateFromSldFunc ? mCreateFromSldFunc( elem ) : nullptr; }
virtual void resolvePaths( QgsStringMap &properties, const QgsPathResolver &pathResolver, bool saving ) override
{
if ( mPathResolverFunc )
@ -159,7 +159,7 @@ class CORE_EXPORT QgsSymbolLayerRegistry
QgsSymbolLayer *createSymbolLayer( const QString &name, const QgsStringMap &properties = QgsStringMap() ) const SIP_FACTORY;
//! create a new instance of symbol layer given symbol layer name and SLD
QgsSymbolLayer *createSymbolLayerFromSld( const QString &name, QDomElement &element ) const;
QgsSymbolLayer *createSymbolLayerFromSld( const QString &name, QDomElement &element ) const SIP_FACTORY;
/** Resolve paths in properties of a particular symbol layer.
* This normally means converting relative paths to absolute paths when loading

View File

@ -2809,6 +2809,48 @@ void QgsSymbolLayerUtils::clearSymbolMap( QgsSymbolMap &symbols )
symbols.clear();
}
QMimeData *QgsSymbolLayerUtils::symbolToMimeData( QgsSymbol *symbol )
{
if ( !symbol )
return nullptr;
std::unique_ptr< QMimeData >mimeData( new QMimeData );
QDomDocument symbolDoc;
QDomElement symbolElem = saveSymbol( QStringLiteral( "symbol" ), symbol, symbolDoc, QgsReadWriteContext() );
symbolDoc.appendChild( symbolElem );
mimeData->setText( symbolDoc.toString() );
mimeData->setImageData( symbolPreviewPixmap( symbol, QSize( 100, 100 ), 18 ).toImage() );
mimeData->setColorData( symbol->color() );
return mimeData.release();
}
QgsSymbol *QgsSymbolLayerUtils::symbolFromMimeData( const QMimeData *data )
{
if ( !data )
return nullptr;
QString text = data->text();
if ( !text.isEmpty() )
{
QDomDocument doc;
QDomElement elem;
if ( doc.setContent( text ) )
{
elem = doc.documentElement();
if ( elem.nodeName() != QStringLiteral( "symbol" ) )
elem = elem.firstChildElement( QStringLiteral( "symbol" ) );
return loadSymbol( elem, QgsReadWriteContext() );
}
}
return nullptr;
}
QgsColorRamp *QgsSymbolLayerUtils::loadColorRamp( QDomElement &element )
{

View File

@ -254,9 +254,9 @@ class CORE_EXPORT QgsSymbolLayerUtils
static bool createSymbolLayerListFromSld( QDomElement &element, QgsWkbTypes::GeometryType geomType, QgsSymbolLayerList &layers );
static QgsSymbolLayer *createFillLayerFromSld( QDomElement &element );
static QgsSymbolLayer *createLineLayerFromSld( QDomElement &element );
static QgsSymbolLayer *createMarkerLayerFromSld( QDomElement &element );
static QgsSymbolLayer *createFillLayerFromSld( QDomElement &element ) SIP_FACTORY;
static QgsSymbolLayer *createLineLayerFromSld( QDomElement &element ) SIP_FACTORY;
static QgsSymbolLayer *createMarkerLayerFromSld( QDomElement &element ) SIP_FACTORY;
static bool convertPolygonSymbolizerToPointMarker( QDomElement &element, QgsSymbolLayerList &layerList );
static bool hasExternalGraphic( QDomElement &element );
@ -365,6 +365,23 @@ class CORE_EXPORT QgsSymbolLayerUtils
static void clearSymbolMap( QgsSymbolMap &symbols );
/**
* Creates new mime data from a \a symbol.
* This also sets the mime color data to match the symbol's color, so that copied symbols
* can be paste in places where a color is expected.
* \see symbolFromMimeData()
* \since QGIS 3.0
*/
static QMimeData *symbolToMimeData( QgsSymbol *symbol ) SIP_FACTORY;
/**
* Attempts to parse \a mime data as a symbol. A new symbol instance will be returned
* if the data was successfully converted to a symbol.
* \see symbolToMimeData()
* \since QGIS 3.0
*/
static QgsSymbol *symbolFromMimeData( const QMimeData *data ) SIP_FACTORY;
/** Creates a color ramp from the settings encoded in an XML element
* \param element DOM element
* \returns new color ramp. Caller takes responsibility for deleting the returned value.
@ -395,7 +412,7 @@ class CORE_EXPORT QgsSymbolLayerUtils
*
* \see colorRampToVariant()
*/
static QgsColorRamp *loadColorRamp( const QVariant &value );
static QgsColorRamp *loadColorRamp( const QVariant &value ) SIP_FACTORY;
/**
* Returns a friendly display name for a color
@ -421,7 +438,7 @@ class CORE_EXPORT QgsSymbolLayerUtils
* \see colorFromMimeData
* \since QGIS 2.5
*/
static QMimeData *colorToMimeData( const QColor &color );
static QMimeData *colorToMimeData( const QColor &color ) SIP_FACTORY;
/**
* Attempts to parse mime data as a color
@ -449,7 +466,7 @@ class CORE_EXPORT QgsSymbolLayerUtils
* \returns mime data containing encoded colors
* \since QGIS 2.5
*/
static QMimeData *colorListToMimeData( const QgsNamedColorList &colorList, const bool allFormats = true );
static QMimeData *colorListToMimeData( const QgsNamedColorList &colorList, const bool allFormats = true ) SIP_FACTORY;
/**
* Exports colors to a gpl GIMP palette file

View File

@ -38,6 +38,7 @@ SET (QGIS_CUSTOMWIDGETS_SRCS
qgsscalewidgetplugin.cpp
# qgsscrollareawidgetplugin.cpp
qgsspinboxplugin.cpp
qgssymbolbuttonplugin.cpp
)
SET (QGIS_CUSTOMWIDGETS_MOC_HDRS
@ -68,6 +69,7 @@ SET (QGIS_CUSTOMWIDGETS_MOC_HDRS
qgsscalewidgetplugin.h
# qgsscrollareawidgetplugin.h
qgsspinboxplugin.h
qgssymbolbuttonplugin.h
)
IF(MSVC)

View File

@ -41,7 +41,7 @@
#include "qgsscalewidgetplugin.h"
//#include "qgsscrollareawidgetplugin.h"
#include "qgsspinboxplugin.h"
#include "qgssymbolbuttonplugin.h"
QgisCustomWidgets::QgisCustomWidgets( QObject *parent )
: QObject( parent )
@ -71,6 +71,7 @@ QgisCustomWidgets::QgisCustomWidgets( QObject *parent )
mWidgets.append( new QgsScaleWidgetPlugin( this ) );
// mWidgets.append( new QgsScrollAreaWidgetPlugin( this ) ); // this is causing troubles at the moment
mWidgets.append( new QgsSpinBoxPlugin( this ) );
mWidgets.append( new QgsSymbolButtonPlugin( this ) );
}
QList<QDesignerCustomWidgetInterface *> QgisCustomWidgets::customWidgets() const

View File

@ -0,0 +1,97 @@
/***************************************************************************
qgssymbolbuttonplugin.cpp
------------------------
Date : 23.07.2017
Copyright : (C) 2017 Nyall Dawson
Email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* 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 "qgiscustomwidgets.h"
#include "qgssymbolbuttonplugin.h"
#include "qgssymbolbutton.h"
QgsSymbolButtonPlugin::QgsSymbolButtonPlugin( QObject *parent )
: QObject( parent )
, mInitialized( false )
{
}
QString QgsSymbolButtonPlugin::name() const
{
return "QgsSymbolButton";
}
QString QgsSymbolButtonPlugin::group() const
{
return QgisCustomWidgets::groupName();
}
QString QgsSymbolButtonPlugin::includeFile() const
{
return "qgssymbolbutton.h";
}
QIcon QgsSymbolButtonPlugin::icon() const
{
return QIcon( ":/images/icons/qgis-icon-60x60.png" );
}
bool QgsSymbolButtonPlugin::isContainer() const
{
return false;
}
QWidget *QgsSymbolButtonPlugin::createWidget( QWidget *parent )
{
return new QgsSymbolButton( parent );
}
bool QgsSymbolButtonPlugin::isInitialized() const
{
return mInitialized;
}
void QgsSymbolButtonPlugin::initialize( QDesignerFormEditorInterface *core )
{
Q_UNUSED( core );
if ( mInitialized )
return;
mInitialized = true;
}
QString QgsSymbolButtonPlugin::toolTip() const
{
return tr( "Select symbol" );
}
QString QgsSymbolButtonPlugin::whatsThis() const
{
return "";
}
QString QgsSymbolButtonPlugin::domXml() const
{
return QString( "<ui language=\"c++\">\n"
" <widget class=\"%1\" name=\"mSymbolButton\">\n"
" <property name=\"geometry\">\n"
" <rect>\n"
" <x>0</x>\n"
" <y>0</y>\n"
" <width>27</width>\n"
" <height>27</height>\n"
" </rect>\n"
" </property>\n"
" </widget>\n"
"</ui>\n" )
.arg( name() );
}

View File

@ -0,0 +1,51 @@
/***************************************************************************
qgssymbolbuttonplugin.h
----------------------
Date : 23.07.2017
Copyright : (C) 2017 Nyall Dawson
Email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* 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 QGSSYMBOLBUTTONPLUGIN_H
#define QGSSYMBOLBUTTONPLUGIN_H
#include <QtGlobal>
#include <QtUiPlugin/QDesignerCustomWidgetInterface>
#include <QtUiPlugin/QDesignerExportWidget>
#include "qgis_customwidgets.h"
class CUSTOMWIDGETS_EXPORT QgsSymbolButtonPlugin : public QObject, public QDesignerCustomWidgetInterface
{
Q_OBJECT
Q_INTERFACES( QDesignerCustomWidgetInterface )
public:
explicit QgsSymbolButtonPlugin( QObject *parent = 0 );
private:
bool mInitialized;
// QDesignerCustomWidgetInterface interface
public:
QString name() const override;
QString group() const override;
QString includeFile() const override;
QIcon icon() const override;
bool isContainer() const override;
QWidget *createWidget( QWidget *parent ) override;
bool isInitialized() const override;
void initialize( QDesignerFormEditorInterface *core ) override;
QString toolTip() const override;
QString whatsThis() const override;
QString domXml() const override;
};
#endif // QGSSYMBOLBUTTONPLUGIN_H

View File

@ -336,6 +336,7 @@ SET(QGIS_GUI_SRCS
qgssubstitutionlistwidget.cpp
qgssqlcomposerdialog.cpp
qgsstatusbar.cpp
qgssymbolbutton.cpp
qgstablewidgetbase.cpp
qgstabwidget.cpp
qgstablewidgetitem.cpp
@ -492,6 +493,7 @@ SET(QGIS_GUI_MOC_HDRS
qgsstatusbar.h
qgssublayersdialog.h
qgssubstitutionlistwidget.h
qgssymbolbutton.h
qgstablewidgetbase.h
qgstabwidget.h
qgstaskmanagerwidget.h

View File

@ -26,7 +26,6 @@ QgsFieldConditionalFormatWidget::QgsFieldConditionalFormatWidget( QWidget *paren
, mLayer( nullptr )
, mEditIndex( 0 )
, mEditing( false )
, mSymbol( nullptr )
{
setupUi( this );
mDeleteButton->hide();
@ -38,7 +37,6 @@ QgsFieldConditionalFormatWidget::QgsFieldConditionalFormatWidget( QWidget *paren
connect( mCancelButton, &QAbstractButton::clicked, this, &QgsFieldConditionalFormatWidget::cancelRule );
connect( mDeleteButton, &QAbstractButton::clicked, this, &QgsFieldConditionalFormatWidget::deleteRule );
connect( listView, &QAbstractItemView::clicked, this, &QgsFieldConditionalFormatWidget::ruleClicked );
connect( btnChangeIcon, &QAbstractButton::clicked, this, &QgsFieldConditionalFormatWidget::updateIcon );
connect( btnBuildExpression, &QAbstractButton::clicked, this, &QgsFieldConditionalFormatWidget::setExpression );
connect( mPresetsList, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsFieldConditionalFormatWidget::presetSet );
btnBackgroundColor->setAllowOpacity( true );
@ -49,27 +47,14 @@ QgsFieldConditionalFormatWidget::QgsFieldConditionalFormatWidget( QWidget *paren
mModel = new QStandardItemModel( listView );
listView->setModel( mModel );
mPresetsList->setModel( mPresetsModel );
btnChangeIcon->setSymbolType( QgsSymbol::Marker );
btnChangeIcon->setSymbol( QgsSymbol::defaultSymbol( QgsWkbTypes::PointGeometry ) );
setPresets( defaultPresets() );
}
QgsFieldConditionalFormatWidget::~QgsFieldConditionalFormatWidget()
{
delete mSymbol;
}
void QgsFieldConditionalFormatWidget::updateIcon()
{
mSymbol = QgsSymbol::defaultSymbol( QgsWkbTypes::PointGeometry );
QgsSymbolSelectorDialog dlg( mSymbol, QgsStyle::defaultStyle(), nullptr, this );
if ( !dlg.exec() )
{
return;
}
QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mSymbol, btnChangeIcon->iconSize() );
btnChangeIcon->setIcon( icon );
}
void QgsFieldConditionalFormatWidget::setExpression()
@ -130,24 +115,14 @@ void QgsFieldConditionalFormatWidget::setFormattingFromStyle( const QgsCondition
{
btnBackgroundColor->setColor( style.backgroundColor() );
btnTextColor->setColor( style.textColor() );
if ( !style.icon().isNull() )
if ( style.symbol() )
{
btnChangeIcon->setSymbol( style.symbol()->clone() );
checkIcon->setChecked( true );
QIcon icon( style.icon() );
btnChangeIcon->setIcon( icon );
}
else
{
checkIcon->setChecked( false );
btnChangeIcon->setIcon( QIcon() );
}
if ( style.symbol() )
{
mSymbol = style.symbol()->clone();
}
else
{
mSymbol = nullptr;
}
QFont font = style.font();
mFontBoldBtn->setChecked( font.bold() );
@ -206,7 +181,6 @@ void QgsFieldConditionalFormatWidget::addNewRule()
void QgsFieldConditionalFormatWidget::reset()
{
mSymbol = nullptr;
mNameEdit->clear();
mRuleEdit->clear();
if ( fieldRadio->isChecked() )
@ -297,9 +271,9 @@ void QgsFieldConditionalFormatWidget::saveRule()
style.setFont( font );
style.setBackgroundColor( backColor );
style.setTextColor( fontColor );
if ( mSymbol && checkIcon->isChecked() )
if ( checkIcon->isChecked() )
{
style.setSymbol( mSymbol );
style.setSymbol( btnChangeIcon->clonedSymbol< QgsMarkerSymbol >() );
}
else
{

View File

@ -96,7 +96,6 @@ class GUI_EXPORT QgsFieldConditionalFormatWidget : public QWidget, private Ui::Q
bool mEditing;
QStandardItemModel *mModel = nullptr;
QStandardItemModel *mPresetsModel = nullptr;
QgsSymbol *mSymbol = nullptr;
QList<QgsConditionalStyle> mPresets;
QList<QgsConditionalStyle> getStyles();
@ -105,7 +104,6 @@ class GUI_EXPORT QgsFieldConditionalFormatWidget : public QWidget, private Ui::Q
private slots:
void setExpression();
void updateIcon();
void presetSet( int index );
bool isCustomSet();
void ruleClicked( const QModelIndex &index );

514
src/gui/qgssymbolbutton.cpp Normal file
View File

@ -0,0 +1,514 @@
/***************************************************************************
qgssymbolbutton.h
-----------------
Date : July 2017
Copyright : (C) 2017 by Nyall Dawson
Email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* 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 "qgssymbolbutton.h"
#include "qgspanelwidget.h"
#include "qgsexpressioncontext.h"
#include "qgsexpressioncontextgenerator.h"
#include "qgsvectorlayer.h"
#include "qgssymbolselectordialog.h"
#include "qgsstyle.h"
#include "qgscolorwidgets.h"
#include "qgscolorschemeregistry.h"
#include "qgscolorswatchgrid.h"
#include "qgssymbollayerutils.h"
#include <QMenu>
#include <QClipboard>
#include <QDrag>
QgsSymbolButton::QgsSymbolButton( QWidget *parent, const QString &dialogTitle )
: QToolButton( parent )
, mDialogTitle( dialogTitle.isEmpty() ? tr( "Symbol Settings" ) : dialogTitle )
{
mSymbol.reset( QgsFillSymbol::createSimple( QgsStringMap() ) );
setAcceptDrops( true );
connect( this, &QAbstractButton::clicked, this, &QgsSymbolButton::showSettingsDialog );
//setup dropdown menu
mMenu = new QMenu( this );
connect( mMenu, &QMenu::aboutToShow, this, &QgsSymbolButton::prepareMenu );
setMenu( mMenu );
setPopupMode( QToolButton::MenuButtonPopup );
}
QSize QgsSymbolButton::minimumSizeHint() const
{
//make sure height of button looks good under different platforms
QSize size = QToolButton::minimumSizeHint();
int fontHeight = fontMetrics().height() * 1.4;
return QSize( size.width(), qMax( size.height(), fontHeight ) );
}
void QgsSymbolButton::setSymbolType( QgsSymbol::SymbolType type )
{
if ( type != mType )
{
switch ( type )
{
case QgsSymbol::Marker:
mSymbol.reset( QgsMarkerSymbol::createSimple( QgsStringMap() ) );
break;
case QgsSymbol::Line:
mSymbol.reset( QgsLineSymbol::createSimple( QgsStringMap() ) );
break;
case QgsSymbol::Fill:
mSymbol.reset( QgsFillSymbol::createSimple( QgsStringMap() ) );
break;
case QgsSymbol::Hybrid:
break;
}
}
updatePreview();
mType = type;
}
void QgsSymbolButton::showSettingsDialog()
{
QgsExpressionContext context;
if ( mExpressionContextGenerator )
context = mExpressionContextGenerator->createExpressionContext();
else
{
context.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( mLayer.data() ) );
}
QgsSymbol *newSymbol = mSymbol->clone();
QgsSymbolWidgetContext symbolContext;
symbolContext.setExpressionContext( &context );
symbolContext.setMapCanvas( mMapCanvas );
QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
if ( panel && panel->dockMode() )
{
QgsSymbolSelectorWidget *d = new QgsSymbolSelectorWidget( newSymbol, QgsStyle::defaultStyle(), mLayer, nullptr );
d->setContext( symbolContext );
connect( d, &QgsPanelWidget::widgetChanged, this, &QgsSymbolButton::updateSymbolFromWidget );
connect( d, &QgsPanelWidget::panelAccepted, this, &QgsSymbolButton::cleanUpSymbolSelector );
panel->openPanel( d );
}
else
{
QgsSymbolSelectorDialog dialog( newSymbol, QgsStyle::defaultStyle(), mLayer, nullptr );
dialog.setWindowTitle( mDialogTitle );
dialog.setContext( symbolContext );
if ( dialog.exec() )
{
setSymbol( newSymbol );
}
else
{
delete newSymbol;
}
// reactivate button's window
activateWindow();
}
}
void QgsSymbolButton::updateSymbolFromWidget()
{
if ( QgsSymbolSelectorWidget *w = qobject_cast<QgsSymbolSelectorWidget *>( sender() ) )
setSymbol( w->symbol()->clone() );
}
void QgsSymbolButton::cleanUpSymbolSelector( QgsPanelWidget *container )
{
QgsSymbolSelectorWidget *w = qobject_cast<QgsSymbolSelectorWidget *>( container );
if ( !w )
return;
delete w->symbol();
}
QgsMapCanvas *QgsSymbolButton::mapCanvas() const
{
return mMapCanvas;
}
void QgsSymbolButton::setMapCanvas( QgsMapCanvas *mapCanvas )
{
mMapCanvas = mapCanvas;
}
QgsVectorLayer *QgsSymbolButton::layer() const
{
return mLayer;
}
void QgsSymbolButton::setLayer( QgsVectorLayer *layer )
{
mLayer = layer;
}
void QgsSymbolButton::registerExpressionContextGenerator( QgsExpressionContextGenerator *generator )
{
mExpressionContextGenerator = generator;
}
void QgsSymbolButton::setSymbol( QgsSymbol *symbol )
{
mSymbol.reset( symbol );
updatePreview();
emit changed();
}
void QgsSymbolButton::setColor( const QColor &color )
{
QColor opaque = color;
opaque.setAlphaF( 1.0 );
if ( opaque == mSymbol->color() )
return;
mSymbol->setColor( opaque );
updatePreview();
emit changed();
}
void QgsSymbolButton::copySymbol()
{
QApplication::clipboard()->setMimeData( QgsSymbolLayerUtils::symbolToMimeData( mSymbol.get() ) );
}
void QgsSymbolButton::pasteSymbol()
{
std::unique_ptr< QgsSymbol > symbol( QgsSymbolLayerUtils::symbolFromMimeData( QApplication::clipboard()->mimeData() ) );
if ( symbol && symbol->type() == mType )
setSymbol( symbol.release() );
}
void QgsSymbolButton::copyColor()
{
QApplication::clipboard()->setMimeData( QgsSymbolLayerUtils::colorToMimeData( mSymbol->color() ) );
}
void QgsSymbolButton::pasteColor()
{
QColor clipColor;
bool hasAlpha = false;
if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor, hasAlpha ) )
{
//paste color
setColor( clipColor );
QgsRecentColorScheme::addRecentColor( clipColor );
}
}
void QgsSymbolButton::mousePressEvent( QMouseEvent *e )
{
if ( e->button() == Qt::RightButton )
{
QToolButton::showMenu();
return;
}
else if ( e->button() == Qt::LeftButton )
{
mDragStartPosition = e->pos();
}
QToolButton::mousePressEvent( e );
}
void QgsSymbolButton::mouseMoveEvent( QMouseEvent *e )
{
//handle dragging colors/symbols from button
if ( !( e->buttons() & Qt::LeftButton ) )
{
//left button not depressed, so not a drag
QToolButton::mouseMoveEvent( e );
return;
}
if ( ( e->pos() - mDragStartPosition ).manhattanLength() < QApplication::startDragDistance() )
{
//mouse not moved, so not a drag
QToolButton::mouseMoveEvent( e );
return;
}
//user is dragging
QDrag *drag = new QDrag( this );
drag->setMimeData( QgsSymbolLayerUtils::colorToMimeData( mSymbol->color() ) );
drag->setPixmap( QgsColorWidget::createDragIcon( mSymbol->color() ) );
drag->exec( Qt::CopyAction );
setDown( false );
}
void QgsSymbolButton::dragEnterEvent( QDragEnterEvent *e )
{
//is dragged data valid color data?
QColor mimeColor;
bool hasAlpha = false;
if ( colorFromMimeData( e->mimeData(), mimeColor, hasAlpha ) )
{
//if so, we accept the drag, and temporarily change the button's color
//to match the dragged color. This gives immediate feedback to the user
//that colors can be dropped here
e->acceptProposedAction();
updatePreview( mimeColor );
}
}
void QgsSymbolButton::dragLeaveEvent( QDragLeaveEvent *e )
{
Q_UNUSED( e );
//reset button color
updatePreview();
}
void QgsSymbolButton::dropEvent( QDropEvent *e )
{
//is dropped data valid format data?
QColor mimeColor;
bool hasAlpha = false;
if ( colorFromMimeData( e->mimeData(), mimeColor, hasAlpha ) )
{
//accept drop and set new color
e->acceptProposedAction();
mimeColor.setAlphaF( 1.0 );
mSymbol->setColor( mimeColor );
QgsRecentColorScheme::addRecentColor( mimeColor );
updatePreview();
emit changed();
}
updatePreview();
}
void QgsSymbolButton::prepareMenu()
{
//we need to tear down and rebuild this menu every time it is shown. Otherwise the space allocated to any
//QgsColorSwatchGridAction is not recalculated by Qt and the swatch grid may not be the correct size
//for the number of colors shown in the grid. Note that we MUST refresh color swatch grids every time this
//menu is opened, otherwise color schemes like the recent color scheme grid are meaningless
mMenu->clear();
QAction *configureAction = new QAction( tr( "Configure symbol..." ), this );
mMenu->addAction( configureAction );
connect( configureAction, &QAction::triggered, this, &QgsSymbolButton::showSettingsDialog );
QAction *copySymbolAction = new QAction( tr( "Copy symbol" ), this );
mMenu->addAction( copySymbolAction );
connect( copySymbolAction, &QAction::triggered, this, &QgsSymbolButton::copySymbol );
QAction *pasteSymbolAction = new QAction( tr( "Paste symbol" ), this );
//enable or disable paste action based on current clipboard contents. We always show the paste
//action, even if it's disabled, to give hint to the user that pasting symbols is possible
std::unique_ptr< QgsSymbol > tempSymbol( QgsSymbolLayerUtils::symbolFromMimeData( QApplication::clipboard()->mimeData() ) );
if ( tempSymbol && tempSymbol->type() == mType )
{
pasteSymbolAction->setIcon( QgsSymbolLayerUtils::symbolPreviewIcon( tempSymbol.get(), QSize( 16, 16 ), 1 ) );
}
else
{
pasteSymbolAction->setEnabled( false );
}
mMenu->addAction( pasteSymbolAction );
connect( pasteSymbolAction, &QAction::triggered, this, &QgsSymbolButton::pasteSymbol );
mMenu->addSeparator();
QgsColorWheel *colorWheel = new QgsColorWheel( mMenu );
colorWheel->setColor( mSymbol->color() );
QgsColorWidgetAction *colorAction = new QgsColorWidgetAction( colorWheel, mMenu, mMenu );
colorAction->setDismissOnColorSelection( false );
connect( colorAction, &QgsColorWidgetAction::colorChanged, this, &QgsSymbolButton::setColor );
mMenu->addAction( colorAction );
QgsColorRampWidget *alphaRamp = new QgsColorRampWidget( mMenu, QgsColorWidget::Alpha, QgsColorRampWidget::Horizontal );
QColor alphaColor = mSymbol->color();
alphaColor.setAlphaF( mSymbol->opacity() );
alphaRamp->setColor( alphaColor );
QgsColorWidgetAction *alphaAction = new QgsColorWidgetAction( alphaRamp, mMenu, mMenu );
alphaAction->setDismissOnColorSelection( false );
connect( alphaAction, &QgsColorWidgetAction::colorChanged, this, [ = ]( const QColor & color )
{
double opacity = color.alphaF();
mSymbol->setOpacity( opacity );
updatePreview();
emit changed();
} );
connect( colorAction, &QgsColorWidgetAction::colorChanged, alphaRamp, [alphaRamp]( const QColor & color ) { alphaRamp->setColor( color, false ); }
);
mMenu->addAction( alphaAction );
//get schemes with ShowInColorButtonMenu flag set
QList< QgsColorScheme * > schemeList = QgsApplication::colorSchemeRegistry()->schemes( QgsColorScheme::ShowInColorButtonMenu );
QList< QgsColorScheme * >::iterator it = schemeList.begin();
for ( ; it != schemeList.end(); ++it )
{
QgsColorSwatchGridAction *colorAction = new QgsColorSwatchGridAction( *it, mMenu, QStringLiteral( "symbology" ), this );
colorAction->setBaseColor( mSymbol->color() );
mMenu->addAction( colorAction );
connect( colorAction, &QgsColorSwatchGridAction::colorChanged, this, &QgsSymbolButton::setColor );
connect( colorAction, &QgsColorSwatchGridAction::colorChanged, this, &QgsSymbolButton::addRecentColor );
}
mMenu->addSeparator();
QAction *copyColorAction = new QAction( tr( "Copy color" ), this );
mMenu->addAction( copyColorAction );
connect( copyColorAction, &QAction::triggered, this, &QgsSymbolButton::copyColor );
QAction *pasteColorAction = new QAction( tr( "Paste color" ), this );
//enable or disable paste action based on current clipboard contents. We always show the paste
//action, even if it's disabled, to give hint to the user that pasting colors is possible
QColor clipColor;
bool hasAlpha = false;
if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor, hasAlpha ) )
{
pasteColorAction->setIcon( createColorIcon( clipColor ) );
}
else
{
pasteColorAction->setEnabled( false );
}
mMenu->addAction( pasteColorAction );
connect( pasteColorAction, &QAction::triggered, this, &QgsSymbolButton::pasteColor );
}
void QgsSymbolButton::addRecentColor( const QColor &color )
{
QgsRecentColorScheme::addRecentColor( color );
}
void QgsSymbolButton::changeEvent( QEvent *e )
{
if ( e->type() == QEvent::EnabledChange )
{
updatePreview();
}
QToolButton::changeEvent( e );
}
void QgsSymbolButton::showEvent( QShowEvent *e )
{
updatePreview();
QToolButton::showEvent( e );
}
void QgsSymbolButton::resizeEvent( QResizeEvent *event )
{
QToolButton::resizeEvent( event );
//recalculate icon size and redraw icon
mIconSize = QSize();
updatePreview();
}
void QgsSymbolButton::updatePreview( const QColor &color, QgsSymbol *tempSymbol )
{
std::unique_ptr< QgsSymbol > previewSymbol;
if ( tempSymbol )
previewSymbol.reset( tempSymbol->clone() );
else
previewSymbol.reset( mSymbol->clone() );
if ( color.isValid() )
previewSymbol->setColor( color );
QSize currentIconSize;
//icon size is button size with a small margin
if ( menu() )
{
if ( !mIconSize.isValid() )
{
//calculate size of push button part of widget (ie, without the menu dropdown button part)
QStyleOptionToolButton opt;
initStyleOption( &opt );
QRect buttonSize = QApplication::style()->subControlRect( QStyle::CC_ToolButton, &opt, QStyle::SC_ToolButton,
this );
//make sure height of icon looks good under different platforms
#ifdef Q_OS_WIN
mIconSize = QSize( buttonSize.width() - 10, height() - 6 );
#else
mIconSize = QSize( buttonSize.width() - 10, height() - 12 );
#endif
}
currentIconSize = mIconSize;
}
else
{
//no menu
#ifdef Q_OS_WIN
currentIconSize = QSize( width() - 10, height() - 6 );
#else
currentIconSize = QSize( width() - 10, height() - 12 );
#endif
}
if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
{
return;
}
//create an icon pixmap
QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( previewSymbol.get(), currentIconSize );
setIconSize( currentIconSize );
setIcon( icon );
}
bool QgsSymbolButton::colorFromMimeData( const QMimeData *mimeData, QColor &resultColor, bool &hasAlpha )
{
hasAlpha = false;
QColor mimeColor = QgsSymbolLayerUtils::colorFromMimeData( mimeData, hasAlpha );
if ( mimeColor.isValid() )
{
resultColor = mimeColor;
return true;
}
//could not get color from mime data
return false;
}
QPixmap QgsSymbolButton::createColorIcon( const QColor &color ) const
{
//create an icon pixmap
QPixmap pixmap( 16, 16 );
pixmap.fill( Qt::transparent );
QPainter p;
p.begin( &pixmap );
//draw color over pattern
p.setBrush( QBrush( color ) );
//draw border
p.setPen( QColor( 197, 197, 197 ) );
p.drawRect( 0, 0, 15, 15 );
p.end();
return pixmap;
}
void QgsSymbolButton::setDialogTitle( const QString &title )
{
mDialogTitle = title;
}
QString QgsSymbolButton::dialogTitle() const
{
return mDialogTitle;
}
QgsSymbol *QgsSymbolButton::symbol()
{
return mSymbol.get();
}

268
src/gui/qgssymbolbutton.h Normal file
View File

@ -0,0 +1,268 @@
/***************************************************************************
qgssymbolbutton.h
-----------------
Date : July 2017
Copyright : (C) 2017 by Nyall Dawson
Email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* 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 QGSSYMBOLBUTTON_H
#define QGSSYMBOLBUTTON_H
#include "qgis_gui.h"
#include "qgis.h"
#include "qgssymbol.h"
#include <QToolButton>
#include <QPointer>
#include <memory>
class QgsMapCanvas;
class QgsVectorLayer;
class QgsExpressionContextGenerator;
class QgsPanelWidget;
/**
* \ingroup gui
* \class QgsSymbolButton
* A button for creating and modifying QgsSymbol settings.
*
* The button shows a preview icon for the current symbol, and will open a detailed symbol editor dialog (or
* panel widget) when clicked.
*
* \since QGIS 3.0
*/
class GUI_EXPORT QgsSymbolButton : public QToolButton
{
Q_OBJECT
Q_PROPERTY( QString dialogTitle READ dialogTitle WRITE setDialogTitle )
public:
/**
* Construct a new symbol button.
* Use \a dialogTitle string to define the title to show in the symbol settings dialog.
*/
QgsSymbolButton( QWidget *parent SIP_TRANSFERTHIS = nullptr, const QString &dialogTitle = QString() );
virtual QSize minimumSizeHint() const override;
/**
* Sets the symbol \a type which the button requires.
* If the type differs from the current symbol type, the symbol will be reset
* to a default symbol style of the new type.
* \see symbolType()
*/
void setSymbolType( QgsSymbol::SymbolType type );
/**
* Returns the symbol type which the button requires.
* \see setSymbolType()
*/
QgsSymbol::SymbolType symbolType() const { return mType; }
/**
* Sets the \a title for the symbol settings dialog window.
* \see dialogTitle()
*/
void setDialogTitle( const QString &title );
/**
* Returns the title for the symbol settings dialog window.
* \see setDialogTitle()
*/
QString dialogTitle() const;
/**
* Returns the current symbol defined by the button.
* \see setSymbol()
* \see changed()
*/
QgsSymbol *symbol();
/**
* Returns a clone of the current symbol (as the specified template type) defined by the button.
* \see setSymbol()
* \see changed()
* \note Not available in Python bindings.
*/
template <class SymbolType> SymbolType *clonedSymbol() SIP_SKIP
{
QgsSymbol *tmpSymbol = mSymbol.get();
SymbolType *symbolCastToType = dynamic_cast<SymbolType *>( tmpSymbol );
if ( symbolCastToType )
{
return symbolCastToType->clone();
}
else
{
//could not cast
return nullptr;
}
}
/**
* Returns the map canvas associated with the widget.
* \see setMapCanvas()
*/
QgsMapCanvas *mapCanvas() const;
/**
* Sets a map \a canvas to associate with the widget. This allows the
* widget to fetch current settings from the map canvas, such as current scale.
* \see mapCanvas()
*/
void setMapCanvas( QgsMapCanvas *canvas );
/**
* Returns the layer associated with the widget.
* \see setLayer()
*/
QgsVectorLayer *layer() const;
/**
* Sets a \a layer to associate with the widget. This allows the
* widget to setup layer related settings within the symbol settings dialog,
* such as correctly populating data defined override buttons.
* \see layer()
*/
void setLayer( QgsVectorLayer *layer );
/**
* Register an expression context generator class that will be used to retrieve
* an expression context for the button when required.
*/
void registerExpressionContextGenerator( QgsExpressionContextGenerator *generator );
public slots:
/**
* Sets the \a symbol for the button. Ownership of \a symbol is transferred to the
* button.
* \see symbol()
* \see changed()
*/
void setSymbol( QgsSymbol *symbol SIP_TRANSFER );
/**
* Sets the current \a color for the symbol. Will emit a changed() signal if the color is different
* to the previous symbol color.
*/
void setColor( const QColor &color );
/** Copies the current symbol to the clipboard.
* \see pasteSymbol()
*/
void copySymbol();
/**
* Pastes a symbol from the clipboard. If clipboard does not contain a valid
* symbol then no change is applied.
* \see copySymbol()
*/
void pasteSymbol();
/**
* Copies the current symbol color to the clipboard.
* \see pasteColor()
*/
void copyColor();
/**
* Pastes a color from the clipboard to the symbol. If clipboard does not contain a valid
* color or string representation of a color, then no change is applied.
* \see copyColor()
*/
void pasteColor();
signals:
/**
* Emitted when the symbol's settings are changed.
* \see symbol()
* \see setSymbol()
*/
void changed();
protected:
void changeEvent( QEvent *e ) override;
void showEvent( QShowEvent *e ) override;
void resizeEvent( QResizeEvent *event ) override;
// Reimplemented to detect right mouse button clicks on the color button and allow dragging colors
void mousePressEvent( QMouseEvent *e ) override;
// Reimplemented to allow dragging colors/symbols from button
void mouseMoveEvent( QMouseEvent *e ) override;
// Reimplemented to accept dragged colors
void dragEnterEvent( QDragEnterEvent *e ) override;
// Reimplemented to reset button appearance after drag leave
void dragLeaveEvent( QDragLeaveEvent *e ) override;
// Reimplemented to accept dropped colors
void dropEvent( QDropEvent *e ) override;
private slots:
void showSettingsDialog();
void updateSymbolFromWidget();
void cleanUpSymbolSelector( QgsPanelWidget *container );
/** Creates the drop-down menu entries
*/
void prepareMenu();
void addRecentColor( const QColor &color );
private:
QString mDialogTitle;
QgsSymbol::SymbolType mType = QgsSymbol::Fill;
QgsMapCanvas *mMapCanvas = nullptr;
QPoint mDragStartPosition;
QMenu *mMenu = nullptr;
QPointer< QgsVectorLayer > mLayer;
QSize mIconSize;
std::unique_ptr< QgsSymbol > mSymbol;
QgsExpressionContextGenerator *mExpressionContextGenerator = nullptr;
/**
* Regenerates the text preview. If \a color is specified, a temporary color preview
* is shown instead.
*/
void updatePreview( const QColor &color = QColor(), QgsSymbol *tempSymbol = nullptr );
/** Attempts to parse mimeData as a color, either via the mime data's color data or by
* parsing a textual representation of a color.
* \returns true if mime data could be intrepreted as a color
* \param mimeData mime data
* \param resultColor QColor to store evaluated color
* \param hasAlpha will be set to true if mime data also included an alpha component
* \see formatFromMimeData
*/
bool colorFromMimeData( const QMimeData *mimeData, QColor &resultColor, bool &hasAlpha );
/**
* Create a \a color icon for display in the drop-down menu.
*/
QPixmap createColorIcon( const QColor &color ) const;
};
#endif // QGSSYMBOLBUTTON_H

0
src/gui/qgsunitselectionwidget.cpp Executable file → Normal file
View File

View File

@ -20,7 +20,6 @@
#include "qgis_gui.h"
class QgsNullSymbolRenderer;
class QgsSymbolSelectorDialog;
class QMenu;

View File

@ -53,6 +53,8 @@ QgsPointClusterRendererWidget::QgsPointClusterRendererWidget( QgsVectorLayer *la
mDistanceUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderMapUnits << QgsUnitTypes::RenderPixels
<< QgsUnitTypes::RenderPoints << QgsUnitTypes::RenderInches );
mCenterSymbolToolButton->setSymbolType( QgsSymbol::Marker );
if ( renderer )
{
mRenderer = QgsPointClusterRenderer::convertFromRenderer( renderer );
@ -79,6 +81,7 @@ QgsPointClusterRendererWidget::QgsPointClusterRendererWidget( QgsVectorLayer *la
mDistanceSpinBox->setValue( mRenderer->tolerance() );
mDistanceUnitWidget->setUnit( mRenderer->toleranceUnit() );
mDistanceUnitWidget->setMapUnitScale( mRenderer->toleranceMapUnitScale() );
mCenterSymbolToolButton->setSymbol( mRenderer->clusterSymbol()->clone() );
blockAllSignals( false );
@ -94,7 +97,10 @@ QgsPointClusterRendererWidget::QgsPointClusterRendererWidget( QgsVectorLayer *la
}
}
updateCenterIcon();
connect( mCenterSymbolToolButton, &QgsSymbolButton::changed, this, &QgsPointClusterRendererWidget::centerSymbolChanged );
mCenterSymbolToolButton->setDialogTitle( tr( "Cluster symbol" ) );
mCenterSymbolToolButton->setLayer( mLayer );
mCenterSymbolToolButton->registerExpressionContextGenerator( this );
}
QgsPointClusterRendererWidget::~QgsPointClusterRendererWidget()
@ -112,6 +118,8 @@ void QgsPointClusterRendererWidget::setContext( const QgsSymbolWidgetContext &co
QgsRendererWidget::setContext( context );
if ( mDistanceUnitWidget )
mDistanceUnitWidget->setMapCanvas( context.mapCanvas() );
if ( mCenterSymbolToolButton )
mCenterSymbolToolButton->setMapCanvas( context.mapCanvas() );
}
void QgsPointClusterRendererWidget::on_mRendererComboBox_currentIndexChanged( int index )
@ -175,53 +183,34 @@ void QgsPointClusterRendererWidget::on_mDistanceUnitWidget_changed()
void QgsPointClusterRendererWidget::blockAllSignals( bool block )
{
mRendererComboBox->blockSignals( block );
mCenterSymbolPushButton->blockSignals( block );
mCenterSymbolToolButton->blockSignals( block );
mDistanceSpinBox->blockSignals( block );
mDistanceUnitWidget->blockSignals( block );
}
void QgsPointClusterRendererWidget::on_mCenterSymbolPushButton_clicked()
QgsExpressionContext QgsPointClusterRendererWidget::createExpressionContext() const
{
if ( !mRenderer || !mRenderer->clusterSymbol() )
{
return;
}
QgsMarkerSymbol *markerSymbol = mRenderer->clusterSymbol()->clone();
QgsSymbolSelectorWidget *dlg = new QgsSymbolSelectorWidget( markerSymbol, QgsStyle::defaultStyle(), mLayer, this );
dlg->setPanelTitle( tr( "Cluster symbol" ) );
dlg->setDockMode( this->dockMode() );
QgsSymbolWidgetContext context = mContext;
QgsExpressionContext context;
if ( mContext.expressionContext() )
context = *mContext.expressionContext();
else
context.appendScopes( mContext.globalProjectAtlasMapLayerScopes( mLayer ) );
QgsExpressionContextScope scope;
scope.addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_CLUSTER_COLOR, "", true ) );
scope.addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_CLUSTER_SIZE, 0, true ) );
QList< QgsExpressionContextScope > scopes = context.additionalExpressionContextScopes();
QList< QgsExpressionContextScope > scopes = mContext.additionalExpressionContextScopes();
scopes << scope;
context.setAdditionalExpressionContextScopes( scopes );
dlg->setContext( context );
connect( dlg, &QgsPanelWidget::widgetChanged, this, &QgsPointClusterRendererWidget::updateCenterSymbolFromWidget );
connect( dlg, &QgsPanelWidget::panelAccepted, this, &QgsPointClusterRendererWidget::cleanUpSymbolSelector );
openPanel( dlg );
}
void QgsPointClusterRendererWidget::updateCenterSymbolFromWidget()
{
QgsSymbolSelectorWidget *dlg = qobject_cast<QgsSymbolSelectorWidget *>( sender() );
QgsSymbol *symbol = dlg->symbol()->clone();
mRenderer->setClusterSymbol( static_cast< QgsMarkerSymbol * >( symbol ) );
updateCenterIcon();
emit widgetChanged();
}
void QgsPointClusterRendererWidget::cleanUpSymbolSelector( QgsPanelWidget *container )
{
if ( container )
Q_FOREACH ( const QgsExpressionContextScope &s, scopes )
{
QgsSymbolSelectorWidget *dlg = qobject_cast<QgsSymbolSelectorWidget *>( container );
delete dlg->symbol();
context << new QgsExpressionContextScope( s );
}
return context;
}
void QgsPointClusterRendererWidget::centerSymbolChanged()
{
mRenderer->setClusterSymbol( mCenterSymbolToolButton->clonedSymbol< QgsMarkerSymbol >() );
emit widgetChanged();
}
void QgsPointClusterRendererWidget::updateRendererFromWidget()
@ -234,17 +223,6 @@ void QgsPointClusterRendererWidget::updateRendererFromWidget()
emit widgetChanged();
}
void QgsPointClusterRendererWidget::updateCenterIcon()
{
QgsMarkerSymbol *symbol = mRenderer->clusterSymbol();
if ( !symbol )
{
return;
}
QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( symbol, mCenterSymbolPushButton->iconSize() );
mCenterSymbolPushButton->setIcon( icon );
}
void QgsPointClusterRendererWidget::setupBlankUi( const QString &layerName )
{
QGridLayout *layout = new QGridLayout( this );

View File

@ -21,6 +21,7 @@
#include "ui_qgspointclusterrendererwidgetbase.h"
#include "qgis.h"
#include "qgsrendererwidget.h"
#include "qgsexpressioncontextgenerator.h"
#include "qgis_gui.h"
class QgsPointClusterRenderer;
@ -31,9 +32,10 @@ class QgsPointClusterRenderer;
* \since QGIS 3.0
*/
class GUI_EXPORT QgsPointClusterRendererWidget: public QgsRendererWidget, private Ui::QgsPointClusterRendererWidgetBase
class GUI_EXPORT QgsPointClusterRendererWidget: public QgsRendererWidget, public QgsExpressionContextGenerator, private Ui::QgsPointClusterRendererWidgetBase
{
Q_OBJECT
public:
/** Returns a new QgsPointClusterRendererWidget.
@ -56,11 +58,12 @@ class GUI_EXPORT QgsPointClusterRendererWidget: public QgsRendererWidget, privat
QgsFeatureRenderer *renderer() override;
void setContext( const QgsSymbolWidgetContext &context ) override;
QgsExpressionContext createExpressionContext() const override;
private:
QgsPointClusterRenderer *mRenderer = nullptr;
void blockAllSignals( bool block );
void updateCenterIcon();
void setupBlankUi( const QString &layerName );
private slots:
@ -68,10 +71,8 @@ class GUI_EXPORT QgsPointClusterRendererWidget: public QgsRendererWidget, privat
void on_mRendererComboBox_currentIndexChanged( int index );
void on_mDistanceSpinBox_valueChanged( double d );
void on_mDistanceUnitWidget_changed();
void on_mCenterSymbolPushButton_clicked();
void on_mRendererSettingsButton_clicked();
void updateCenterSymbolFromWidget();
void cleanUpSymbolSelector( QgsPanelWidget *container );
void centerSymbolChanged();
void updateRendererFromWidget();
};

View File

@ -53,6 +53,7 @@ QgsPointDisplacementRendererWidget::QgsPointDisplacementRendererWidget( QgsVecto
mLabelFontButton->setMode( QgsFontButton::ModeQFont );
mDistanceUnitWidget->setUnits( QgsUnitTypes::RenderUnitList() << QgsUnitTypes::RenderMillimeters << QgsUnitTypes::RenderMetersInMapUnits << QgsUnitTypes::RenderMapUnits << QgsUnitTypes::RenderPixels
<< QgsUnitTypes::RenderPoints << QgsUnitTypes::RenderInches );
mCenterSymbolToolButton->setSymbolType( QgsSymbol::Marker );
if ( renderer )
{
@ -118,6 +119,7 @@ QgsPointDisplacementRendererWidget::QgsPointDisplacementRendererWidget( QgsVecto
mDistanceSpinBox->setValue( mRenderer->tolerance() );
mDistanceUnitWidget->setUnit( mRenderer->toleranceUnit() );
mDistanceUnitWidget->setMapUnitScale( mRenderer->toleranceMapUnitScale() );
mCenterSymbolToolButton->setSymbol( mRenderer->centerSymbol()->clone() );
mPlacementComboBox->setCurrentIndex( mPlacementComboBox->findData( mRenderer->placement() ) );
@ -150,8 +152,10 @@ QgsPointDisplacementRendererWidget::QgsPointDisplacementRendererWidget( QgsVecto
connect( mMinLabelScaleWidget, &QgsScaleWidget::scaleChanged, this, &QgsPointDisplacementRendererWidget::minLabelScaleChanged );
connect( mLabelFontButton, &QgsFontButton::changed, this, &QgsPointDisplacementRendererWidget::labelFontChanged );
updateCenterIcon();
connect( mCenterSymbolToolButton, &QgsSymbolButton::changed, this, &QgsPointDisplacementRendererWidget::centerSymbolChanged );
mCenterSymbolToolButton->setDialogTitle( tr( "Center symbol" ) );
mCenterSymbolToolButton->setLayer( mLayer );
mCenterSymbolToolButton->registerExpressionContextGenerator( this );
}
QgsPointDisplacementRendererWidget::~QgsPointDisplacementRendererWidget()
@ -174,6 +178,29 @@ void QgsPointDisplacementRendererWidget::setContext( const QgsSymbolWidgetContex
mMinLabelScaleWidget->setMapCanvas( context.mapCanvas() );
mMinLabelScaleWidget->setShowCurrentScaleButton( true );
}
if ( mCenterSymbolToolButton )
{
mCenterSymbolToolButton->setMapCanvas( context.mapCanvas() );
}
}
QgsExpressionContext QgsPointDisplacementRendererWidget::createExpressionContext() const
{
QgsExpressionContext context;
if ( mContext.expressionContext() )
context = *mContext.expressionContext();
else
context.appendScopes( mContext.globalProjectAtlasMapLayerScopes( mLayer ) );
QgsExpressionContextScope scope;
scope.addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_CLUSTER_COLOR, "", true ) );
scope.addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_CLUSTER_SIZE, 0, true ) );
QList< QgsExpressionContextScope > scopes = mContext.additionalExpressionContextScopes();
scopes << scope;
Q_FOREACH ( const QgsExpressionContextScope &s, scopes )
{
context << new QgsExpressionContextScope( s );
}
return context;
}
void QgsPointDisplacementRendererWidget::on_mLabelFieldComboBox_currentIndexChanged( const QString &text )
@ -348,55 +375,18 @@ void QgsPointDisplacementRendererWidget::blockAllSignals( bool block )
mCircleModificationSpinBox->blockSignals( block );
mScaleDependentLabelsCheckBox->blockSignals( block );
mMinLabelScaleWidget->blockSignals( block );
mCenterSymbolPushButton->blockSignals( block );
mCenterSymbolToolButton->blockSignals( block );
mDistanceSpinBox->blockSignals( block );
mDistanceUnitWidget->blockSignals( block );
mPlacementComboBox->blockSignals( block );
}
void QgsPointDisplacementRendererWidget::on_mCenterSymbolPushButton_clicked()
void QgsPointDisplacementRendererWidget::centerSymbolChanged()
{
if ( !mRenderer || !mRenderer->centerSymbol() )
{
return;
}
QgsMarkerSymbol *markerSymbol = mRenderer->centerSymbol()->clone();
QgsSymbolSelectorWidget *dlg = new QgsSymbolSelectorWidget( markerSymbol, QgsStyle::defaultStyle(), mLayer, this );
dlg->setPanelTitle( tr( "Center symbol" ) );
QgsSymbolWidgetContext context = mContext;
QgsExpressionContextScope scope;
scope.addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_CLUSTER_COLOR, "", true ) );
scope.addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_CLUSTER_SIZE, 0, true ) );
QList< QgsExpressionContextScope > scopes = context.additionalExpressionContextScopes();
scopes << scope;
context.setAdditionalExpressionContextScopes( scopes );
dlg->setContext( context );
connect( dlg, &QgsPanelWidget::widgetChanged, this, &QgsPointDisplacementRendererWidget::updateCenterSymbolFromWidget );
connect( dlg, &QgsPanelWidget::panelAccepted, this, &QgsPointDisplacementRendererWidget::cleanUpSymbolSelector );
openPanel( dlg );
}
void QgsPointDisplacementRendererWidget::updateCenterSymbolFromWidget()
{
QgsSymbolSelectorWidget *dlg = qobject_cast<QgsSymbolSelectorWidget *>( sender() );
QgsSymbol *symbol = dlg->symbol()->clone();
mRenderer->setCenterSymbol( static_cast< QgsMarkerSymbol * >( symbol ) );
updateCenterIcon();
mRenderer->setCenterSymbol( mCenterSymbolToolButton->clonedSymbol< QgsMarkerSymbol >() );
emit widgetChanged();
}
void QgsPointDisplacementRendererWidget::cleanUpSymbolSelector( QgsPanelWidget *container )
{
if ( container )
{
QgsSymbolSelectorWidget *dlg = qobject_cast<QgsSymbolSelectorWidget *>( container );
delete dlg->symbol();
}
}
void QgsPointDisplacementRendererWidget::updateRendererFromWidget()
{
QgsRendererWidget *w = qobject_cast<QgsRendererWidget *>( sender() );
@ -407,17 +397,6 @@ void QgsPointDisplacementRendererWidget::updateRendererFromWidget()
emit widgetChanged();
}
void QgsPointDisplacementRendererWidget::updateCenterIcon()
{
QgsMarkerSymbol *symbol = mRenderer->centerSymbol();
if ( !symbol )
{
return;
}
QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( symbol, mCenterSymbolPushButton->iconSize() );
mCenterSymbolPushButton->setIcon( icon );
}
void QgsPointDisplacementRendererWidget::setupBlankUi( const QString &layerName )
{
QLabel *label = new QLabel( tr( "The point displacement renderer only applies to (single) point layers. \n'%1' is not a point layer and cannot be displayed by the point displacement renderer" ).arg( layerName ), this );

View File

@ -21,6 +21,7 @@
#include "ui_qgspointdisplacementrendererwidgetbase.h"
#include "qgis.h"
#include "qgsrendererwidget.h"
#include "qgsexpressioncontextgenerator.h"
#include "qgis_gui.h"
class QgsPointDisplacementRenderer;
@ -28,7 +29,7 @@ class QgsPointDisplacementRenderer;
/** \ingroup gui
* \class QgsPointDisplacementRendererWidget
*/
class GUI_EXPORT QgsPointDisplacementRendererWidget: public QgsRendererWidget, private Ui::QgsPointDisplacementRendererWidgetBase
class GUI_EXPORT QgsPointDisplacementRendererWidget: public QgsRendererWidget, public QgsExpressionContextGenerator, private Ui::QgsPointDisplacementRendererWidgetBase
{
Q_OBJECT
public:
@ -39,11 +40,12 @@ class GUI_EXPORT QgsPointDisplacementRendererWidget: public QgsRendererWidget, p
QgsFeatureRenderer *renderer() override;
void setContext( const QgsSymbolWidgetContext &context ) override;
QgsExpressionContext createExpressionContext() const override;
private:
QgsPointDisplacementRenderer *mRenderer = nullptr;
void blockAllSignals( bool block );
void updateCenterIcon();
void setupBlankUi( const QString &layerName );
private slots:
@ -59,10 +61,8 @@ class GUI_EXPORT QgsPointDisplacementRendererWidget: public QgsRendererWidget, p
void on_mCircleModificationSpinBox_valueChanged( double d );
void on_mScaleDependentLabelsCheckBox_stateChanged( int state );
void minLabelScaleChanged( double scale );
void on_mCenterSymbolPushButton_clicked();
void on_mRendererSettingsButton_clicked();
void updateCenterSymbolFromWidget();
void cleanUpSymbolSelector( QgsPanelWidget *container );
void centerSymbolChanged();
void updateRendererFromWidget();
};

View File

@ -28,7 +28,6 @@ class QgsDataDefinedSizeLegendWidget;
class QgsVectorLayer;
class QgsStyle;
class QgsFeatureRenderer;
class QgsSymbolSelectorDialog;
class QgsMapCanvas;
/** \ingroup gui

View File

@ -96,8 +96,11 @@
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QComboBox" name="mShapeComboBox"/>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="mShapeStyleButton">
<widget class="QgsSymbolButton" name="mShapeStyleButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
@ -109,9 +112,6 @@
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QComboBox" name="mShapeComboBox"/>
</item>
</layout>
</widget>
</item>
@ -122,6 +122,11 @@
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsDoubleSpinBox</class>
<extends>QDoubleSpinBox</extends>
<header>qgsdoublespinbox.h</header>
</customwidget>
<customwidget>
<class>QgsScrollArea</class>
<extends>QScrollArea</extends>
@ -135,9 +140,9 @@
<container>1</container>
</customwidget>
<customwidget>
<class>QgsDoubleSpinBox</class>
<extends>QDoubleSpinBox</extends>
<header>qgsdoublespinbox.h</header>
<class>QgsSymbolButton</class>
<extends>QToolButton</extends>
<header>qgssymbolbutton.h</header>
</customwidget>
</customwidgets>
<tabstops>

View File

@ -663,6 +663,11 @@
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>QgsDoubleSpinBox</class>
<extends>QDoubleSpinBox</extends>
<header>qgsdoublespinbox.h</header>
</customwidget>
<customwidget>
<class>QgsScrollArea</class>
<extends>QScrollArea</extends>
@ -681,11 +686,6 @@
<header>qgscollapsiblegroupbox.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsDoubleSpinBox</class>
<extends>QDoubleSpinBox</extends>
<header>qgsdoublespinbox.h</header>
</customwidget>
<customwidget>
<class>QgsSpinBox</class>
<extends>QSpinBox</extends>

View File

@ -15,7 +15,13 @@
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="1">
<widget class="QPushButton" name="mFrameStyleButton">
<widget class="QgsSymbolButton" name="mFrameStyleButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
@ -206,7 +212,13 @@
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="mMapMarkerButton">
<widget class="QgsSymbolButton" name="mMapMarkerButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
@ -241,6 +253,11 @@
<header>qgscollapsiblegroupbox.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsSymbolButton</class>
<extends>QToolButton</extends>
<header>qgssymbolbutton.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>mMapPositionFixedCheckBox</tabstop>

View File

@ -180,28 +180,6 @@
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QPushButton" name="mLineSymbolButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="mMarkerSymbolLabel">
<property name="text">
@ -209,28 +187,6 @@
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QPushButton" name="mMarkerSymbolButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="7" column="0" colspan="2">
<widget class="Line" name="line_3">
<property name="orientation">
@ -300,6 +256,50 @@
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QgsSymbolButton" name="mLineSymbolButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QgsSymbolButton" name="mMarkerSymbolButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
<zorder>mOffsetYEdit</zorder>
<zorder>mOffsetXEdit</zorder>
@ -334,6 +334,11 @@
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsSymbolButton</class>
<extends>QToolButton</extends>
<header>qgssymbolbutton.h</header>
</customwidget>
<customwidget>
<class>QgsFontButton</class>
<extends>QToolButton</extends>

View File

@ -62,28 +62,6 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="mSymbolButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer">
<property name="orientation">
@ -110,6 +88,28 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QgsSymbolButton" name="mSymbolButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@ -126,6 +126,11 @@
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsSymbolButton</class>
<extends>QToolButton</extends>
<header>qgssymbolbutton.h</header>
</customwidget>
<customwidget>
<class>QgsFontButton</class>
<extends>QToolButton</extends>
@ -142,7 +147,7 @@
<connection>
<sender>grpEnable</sender>
<signal>toggled(bool)</signal>
<receiver>mSymbolButton</receiver>
<receiver>mLineSymbolLabel</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">

View File

@ -357,7 +357,7 @@
</widget>
</item>
<item>
<widget class="QToolButton" name="btnChangeIcon">
<widget class="QgsSymbolButton" name="btnChangeIcon">
<property name="enabled">
<bool>false</bool>
</property>
@ -384,19 +384,6 @@
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
@ -599,6 +586,11 @@
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsSymbolButton</class>
<extends>QToolButton</extends>
<header>qgssymbolbutton.h</header>
</customwidget>
<customwidget>
<class>QgsColorButton</class>
<extends>QToolButton</extends>

View File

@ -136,13 +136,6 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="mCenterSymbolPushButton">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QPushButton" name="mRendererSettingsButton">
<property name="text">
@ -272,14 +265,26 @@
</layout>
</widget>
</item>
<item row="0" column="1">
<widget class="QgsSymbolButton" name="mCenterSymbolToolButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsColorButton</class>
<extends>QToolButton</extends>
<header>qgscolorbutton.h</header>
<container>1</container>
<class>QgsDoubleSpinBox</class>
<extends>QDoubleSpinBox</extends>
<header>qgsdoublespinbox.h</header>
</customwidget>
<customwidget>
<class>QgsCollapsibleGroupBoxBasic</class>
@ -288,9 +293,15 @@
<container>1</container>
</customwidget>
<customwidget>
<class>QgsDoubleSpinBox</class>
<extends>QDoubleSpinBox</extends>
<header>qgsdoublespinbox.h</header>
<class>QgsSymbolButton</class>
<extends>QToolButton</extends>
<header>qgssymbolbutton.h</header>
</customwidget>
<customwidget>
<class>QgsColorButton</class>
<extends>QToolButton</extends>
<header>qgscolorbutton.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsFontButton</class>
@ -310,7 +321,7 @@
</customwidget>
</customwidgets>
<tabstops>
<tabstop>mCenterSymbolPushButton</tabstop>
<tabstop>mCenterSymbolToolButton</tabstop>
<tabstop>mRendererComboBox</tabstop>
<tabstop>mRendererSettingsButton</tabstop>
<tabstop>mDistanceSpinBox</tabstop>

View File

@ -26,13 +26,6 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="1">
<widget class="QPushButton" name="mCenterSymbolPushButton">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="mRendererComboBox"/>
</item>
@ -98,6 +91,19 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QgsSymbolButton" name="mCenterSymbolToolButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
@ -106,6 +112,11 @@
<extends>QDoubleSpinBox</extends>
<header>qgsdoublespinbox.h</header>
</customwidget>
<customwidget>
<class>QgsSymbolButton</class>
<extends>QToolButton</extends>
<header>qgssymbolbutton.h</header>
</customwidget>
<customwidget>
<class>QgsUnitSelectionWidget</class>
<extends>QWidget</extends>
@ -114,7 +125,7 @@
</customwidget>
</customwidgets>
<tabstops>
<tabstop>mCenterSymbolPushButton</tabstop>
<tabstop>mCenterSymbolToolButton</tabstop>
<tabstop>mRendererComboBox</tabstop>
<tabstop>mRendererSettingsButton</tabstop>
<tabstop>mDistanceSpinBox</tabstop>

View File

@ -126,6 +126,7 @@ ADD_PYTHON_TEST(PyQgsRenderer test_qgsrenderer.py)
ADD_PYTHON_TEST(PyQgsRulebasedRenderer test_qgsrulebasedrenderer.py)
ADD_PYTHON_TEST(PyQgsSingleSymbolRenderer test_qgssinglesymbolrenderer.py)
ADD_PYTHON_TEST(PyQgsShapefileProvider test_provider_shapefile.py)
ADD_PYTHON_TEST(PyQgsSymbolButton test_qgssymbolbutton.py)
ADD_PYTHON_TEST(PyQgsTabfileProvider test_provider_tabfile.py)
ADD_PYTHON_TEST(PyQgsTabWidget test_qgstabwidget.py)
ADD_PYTHON_TEST(PyQgsTextRenderer test_qgstextrenderer.py)

View File

@ -0,0 +1,121 @@
# -*- coding: utf-8 -*-
"""QGIS Unit tests for QgsSymbolButton.
.. note:: 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.
"""
__author__ = 'Nyall Dawson'
__date__ = '23/07/2017'
__copyright__ = 'Copyright 2017, The QGIS Project'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
import qgis # NOQA
from qgis.core import QgsFillSymbol, QgsMarkerSymbol, QgsSymbol
from qgis.gui import QgsSymbolButton, QgsMapCanvas
from qgis.testing import start_app, unittest
from qgis.PyQt.QtGui import QColor, QFont
from qgis.PyQt.QtTest import QSignalSpy
from utilities import getTestFont
start_app()
class TestQgsSymbolButton(unittest.TestCase):
def testGettersSetters(self):
button = QgsSymbolButton()
canvas = QgsMapCanvas()
button.setDialogTitle('test title')
self.assertEqual(button.dialogTitle(), 'test title')
button.setMapCanvas(canvas)
self.assertEqual(button.mapCanvas(), canvas)
button.setSymbolType(QgsSymbol.Line)
self.assertEqual(button.symbolType(), QgsSymbol.Line)
def testSettingSymbolType(self):
button = QgsSymbolButton()
button.setSymbolType(QgsSymbol.Marker)
symbol = QgsMarkerSymbol.createSimple({})
symbol.setColor(QColor(255, 0, 0))
button.setSymbol(symbol)
# if same symbol type, existing symbol should be kept
button.setSymbolType(QgsSymbol.Marker)
self.assertEqual(button.symbol(), symbol)
# if setting different symbol type, symbol should be reset to new type
button.setSymbolType(QgsSymbol.Fill)
self.assertTrue(isinstance(button.symbol(), QgsFillSymbol))
def testPasteSymbol(self):
button = QgsSymbolButton()
button.setSymbolType(QgsSymbol.Marker)
symbol = QgsMarkerSymbol.createSimple({})
symbol.setColor(QColor(255, 0, 0))
button.setSymbol(symbol)
button2 = QgsSymbolButton()
button2.setSymbolType(QgsSymbol.Marker)
symbol2 = QgsMarkerSymbol.createSimple({})
symbol2.setColor(QColor(0, 255, 0))
button2.setSymbol(symbol2)
button.copySymbol()
button2.pasteSymbol()
self.assertEqual(button2.symbol().color(), QColor(255, 0, 0))
# try pasting incompatible symbol
button2.setSymbolType(QgsSymbol.Fill)
fill_symbol = QgsFillSymbol.createSimple({})
fill_symbol.setColor(QColor(0, 0, 255))
button2.setSymbol(fill_symbol)
button.copySymbol() # copied a marker symbol
button2.pasteSymbol() # should have no effect
self.assertEqual(button2.symbol(), fill_symbol)
def testSetGetSymbol(self):
button = QgsSymbolButton()
symbol = QgsMarkerSymbol.createSimple({})
symbol.setColor(QColor(255, 0, 0))
signal_spy = QSignalSpy(button.changed)
button.setSymbol(symbol)
self.assertEqual(len(signal_spy), 1)
r = button.symbol()
self.assertEqual(r.color(), QColor(255, 0, 0))
def testSetColor(self):
button = QgsSymbolButton()
symbol = QgsMarkerSymbol.createSimple({})
symbol.setColor(QColor(255, 255, 0))
button.setSymbol(symbol)
signal_spy = QSignalSpy(button.changed)
button.setColor(QColor(0, 255, 0))
self.assertEqual(len(signal_spy), 1)
r = button.symbol()
self.assertEqual(r.color().name(), QColor(0, 255, 0).name())
# set same color, should not emit signal
button.setColor(QColor(0, 255, 0))
self.assertEqual(len(signal_spy), 1)
# color with transparency - should be stripped
button.setColor(QColor(0, 255, 0, 100))
r = button.symbol()
self.assertEqual(r.color(), QColor(0, 255, 0))
if __name__ == '__main__':
unittest.main()

View File

@ -14,9 +14,12 @@ __revision__ = '$Format:%H$'
import qgis # NOQA
from qgis.core import QgsSymbolLayerUtils
from qgis.core import QgsSymbolLayerUtils, QgsMarkerSymbol
from qgis.PyQt.QtGui import QColor
from qgis.PyQt.QtCore import QSizeF, QPointF
from qgis.testing import unittest
from qgis.testing import unittest, start_app
start_app()
class PyQgsSymbolLayerUtils(unittest.TestCase):
@ -49,6 +52,20 @@ class PyQgsSymbolLayerUtils(unittest.TestCase):
s2 = QgsSymbolLayerUtils.decodePoint('')
self.assertEqual(s2, QPointF())
def testSymbolToFromMimeData(self):
"""
Test converting symbols to and from mime data
"""
symbol = QgsMarkerSymbol.createSimple({})
symbol.setColor(QColor(255, 0, 255))
self.assertFalse(QgsSymbolLayerUtils.symbolFromMimeData(None))
self.assertFalse(QgsSymbolLayerUtils.symbolToMimeData(None))
mime = QgsSymbolLayerUtils.symbolToMimeData(symbol)
self.assertTrue(mime is not None)
symbol2 = QgsSymbolLayerUtils.symbolFromMimeData(mime)
self.assertTrue(symbol2 is not None)
self.assertEqual(symbol2.color().name(), symbol.color().name())
if __name__ == '__main__':
unittest.main()