QGIS API Documentation 3.41.0-Master (57ec4277f5e)
Loading...
Searching...
No Matches
qgslegendpatchshapebutton.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgslegendpatchshapebutton.cpp
3 -----------------
4 Date : April 2020
5 Copyright : (C) 2020 by Nyall Dawson
6 Email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
17#include "moc_qgslegendpatchshapebutton.cpp"
19#include "qgis.h"
20#include "qgsguiutils.h"
21#include "qgsfillsymbol.h"
22#include "qgsmarkersymbol.h"
23#include "qgslinesymbol.h"
24
25#include <QMenu>
26#include <QBuffer>
27
28QgsLegendPatchShapeButton::QgsLegendPatchShapeButton( QWidget *parent, const QString &dialogTitle )
29 : QToolButton( parent )
30 , mShape( QgsStyle::defaultStyle()->defaultPatch( Qgis::SymbolType::Fill, QSizeF( 10, 5 ) ) )
31 , mDialogTitle( dialogTitle.isEmpty() ? tr( "Legend Patch Shape" ) : dialogTitle )
32{
33 mPreviewSymbol.reset( QgsFillSymbol::createSimple( QVariantMap() ) );
34
35 connect( this, &QAbstractButton::clicked, this, &QgsLegendPatchShapeButton::showSettingsDialog );
36
37 //setup dropdown menu
38 mMenu = new QMenu( this );
39 connect( mMenu, &QMenu::aboutToShow, this, &QgsLegendPatchShapeButton::prepareMenu );
40 setMenu( mMenu );
41 setPopupMode( QToolButton::MenuButtonPopup );
42
43 //make sure height of button looks good under different platforms
44 QSize size = QToolButton::minimumSizeHint();
45 int fontHeight = static_cast<int>( Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 2.0 );
46 mSizeHint = QSize( size.width(), std::max( size.height(), fontHeight ) );
47}
48
50
52{
53 return mSizeHint;
54}
55
57{
58 return mSizeHint;
59}
60
62{
63 if ( mPreviewSymbol->type() != type )
64 {
65 switch ( type )
66 {
68 mPreviewSymbol.reset( QgsMarkerSymbol::createSimple( QVariantMap() ) );
69 break;
70
72 mPreviewSymbol.reset( QgsLineSymbol::createSimple( QVariantMap() ) );
73 break;
74
76 mPreviewSymbol.reset( QgsFillSymbol::createSimple( QVariantMap() ) );
77 break;
78
80 break;
81 }
82 }
83
84 if ( type != mType )
85 {
86 mType = type;
88 }
89
90 updatePreview();
91}
92
94{
95 mPreviewSymbol.reset( symbol );
96 updatePreview();
97}
98
99void QgsLegendPatchShapeButton::showSettingsDialog()
100{
102 if ( panel && panel->dockMode() )
103 {
104 QgsLegendPatchShapeWidget *widget = new QgsLegendPatchShapeWidget( this, mShape );
105 connect( widget, &QgsLegendPatchShapeWidget::changed, this, [=] {
106 setShape( widget->shape() );
107 } );
108 widget->setPanelTitle( mDialogTitle );
109 panel->openPanel( widget );
110 }
111}
112
114{
115 switch ( mType )
116 {
118 mShape = QgsStyle::defaultStyle()->defaultPatch( Qgis::SymbolType::Marker, QSizeF( 10, 5 ) );
119 break;
120
122 mShape = QgsStyle::defaultStyle()->defaultPatch( Qgis::SymbolType::Line, QSizeF( 10, 5 ) );
123 break;
124
126 mShape = QgsStyle::defaultStyle()->defaultPatch( Qgis::SymbolType::Fill, QSizeF( 10, 5 ) );
127 break;
128
130 break;
131 }
132 mIsDefault = true;
133 updatePreview();
134 emit changed();
135}
136
138{
139 mMessageBar = bar;
140}
141
143{
144 return mMessageBar;
145}
146
148{
149 mShape = shape.symbolType() == mType ? shape : QgsLegendPatchShape();
150 mIsDefault = mShape.isNull();
151 if ( mIsDefault )
152 {
153 switch ( mType )
154 {
156 mShape = QgsStyle::defaultStyle()->defaultPatch( Qgis::SymbolType::Marker, QSizeF( 10, 5 ) );
157 break;
158
160 mShape = QgsStyle::defaultStyle()->defaultPatch( Qgis::SymbolType::Line, QSizeF( 10, 5 ) );
161 break;
162
164 mShape = QgsStyle::defaultStyle()->defaultPatch( Qgis::SymbolType::Fill, QSizeF( 10, 5 ) );
165 break;
166
168 break;
169 }
170 }
171
172 updatePreview();
173 emit changed();
174}
175
177{
178 if ( e->button() == Qt::RightButton )
179 {
180 QToolButton::showMenu();
181 return;
182 }
183 QToolButton::mousePressEvent( e );
184}
185
186void QgsLegendPatchShapeButton::prepareMenu()
187{
188 mMenu->clear();
189
190 QAction *configureAction = new QAction( tr( "Configure Patch…" ), this );
191 mMenu->addAction( configureAction );
192 connect( configureAction, &QAction::triggered, this, &QgsLegendPatchShapeButton::showSettingsDialog );
193
194 QAction *defaultAction = new QAction( tr( "Reset to Default" ), this );
195 mMenu->addAction( defaultAction );
196 connect( defaultAction, &QAction::triggered, this, [=] { setToDefault(); emit changed(); } );
197
198 mMenu->addSeparator();
199
201 patchNames.sort();
202 const int iconSize = QgsGuiUtils::scaleIconSize( 16 );
203 for ( const QString &name : std::as_const( patchNames ) )
204 {
206 if ( shape.symbolType() == mType )
207 {
208 if ( const QgsSymbol *symbol = QgsStyle::defaultStyle()->previewSymbolForPatchShape( shape ) )
209 {
210 QIcon icon = QgsSymbolLayerUtils::symbolPreviewPixmap( symbol, QSize( iconSize, iconSize ), 1, nullptr, false, nullptr, &shape, QgsScreenProperties( screen() ) );
211 QAction *action = new QAction( name, this );
212 action->setIcon( icon );
213 connect( action, &QAction::triggered, this, [=] { loadPatchFromStyle( name ); } );
214 mMenu->addAction( action );
215 }
216 }
217 }
218}
219
220void QgsLegendPatchShapeButton::loadPatchFromStyle( const QString &name )
221{
222 if ( !QgsStyle::defaultStyle()->legendPatchShapeNames().contains( name ) )
223 return;
224
226 setShape( newShape );
227}
228
230{
231 if ( e->type() == QEvent::EnabledChange )
232 {
233 updatePreview();
234 }
235 QToolButton::changeEvent( e );
236}
237
239{
240 updatePreview();
241 QToolButton::showEvent( e );
242}
243
244void QgsLegendPatchShapeButton::resizeEvent( QResizeEvent *event )
245{
246 QToolButton::resizeEvent( event );
247 //recalculate icon size and redraw icon
248 mIconSize = QSize();
249 updatePreview();
250}
251
252void QgsLegendPatchShapeButton::updatePreview()
253{
254 QSize currentIconSize;
255 //icon size is button size with a small margin
256 if ( menu() )
257 {
258 if ( !mIconSize.isValid() )
259 {
260 //calculate size of push button part of widget (ie, without the menu dropdown button part)
261 QStyleOptionToolButton opt;
262 initStyleOption( &opt );
263 QRect buttonSize = QApplication::style()->subControlRect( QStyle::CC_ToolButton, &opt, QStyle::SC_ToolButton, this );
264 //make sure height of icon looks good under different platforms
265#ifdef Q_OS_WIN
266 mIconSize = QSize( buttonSize.width() - 10, height() - 6 );
267#else
268 mIconSize = QSize( buttonSize.width() - 10, height() - 12 );
269#endif
270 }
271 currentIconSize = mIconSize;
272 }
273 else
274 {
275 //no menu
276#ifdef Q_OS_WIN
277 currentIconSize = QSize( width() - 10, height() - 6 );
278#else
279 currentIconSize = QSize( width() - 10, height() - 12 );
280#endif
281 }
282
283 if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
284 {
285 return;
286 }
287
288 //create an icon pixmap
289 QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mPreviewSymbol.get(), currentIconSize, currentIconSize.height() / 10, &mShape, QgsScreenProperties( screen() ) );
290 setIconSize( currentIconSize );
291 setIcon( icon );
292
293 // set tooltip
294 // create very large preview image
295
296 int width = static_cast<int>( Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 23 );
297 int height = static_cast<int>( width / 1.61803398875 ); // golden ratio
298
299 QPixmap pm = QgsSymbolLayerUtils::symbolPreviewPixmap( mPreviewSymbol.get(), QSize( width, height ), height / 20, nullptr, false, nullptr, &mShape, QgsScreenProperties( screen() ) );
300 QByteArray data;
301 QBuffer buffer( &data );
302 pm.save( &buffer, "PNG", 100 );
303 setToolTip( QStringLiteral( "<img src='data:image/png;base64, %3' width=\"%4\">" ).arg( QString( data.toBase64() ) ).arg( width ) );
304}
305
307{
308 mDialogTitle = title;
309}
310
312{
313 return mDialogTitle;
314}
315
317{
318 return mIsDefault ? QgsLegendPatchShape() : mShape;
319}
The Qgis class provides global constants for use throughout the application.
Definition qgis.h:54
SymbolType
Symbol types.
Definition qgis.h:574
@ Marker
Marker symbol.
@ Line
Line symbol.
@ Fill
Fill symbol.
@ Hybrid
Hybrid symbol.
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition qgis.h:5775
static QgsFillSymbol * createSimple(const QVariantMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties.
void setSymbolType(Qgis::SymbolType type)
Sets the symbol type which the button requires.
void setToDefault()
Resets the shape to the default shape.
QgsLegendPatchShapeButton(QWidget *parent=nullptr, const QString &dialogTitle=QString())
Construct a new patch shape button with the specified parent widget.
QgsMessageBar * messageBar() const
Returns the message bar associated with the widget.
QgsLegendPatchShape shape()
Returns the current shape defined by the button.
void setDialogTitle(const QString &title)
Sets the title for the symbol settings dialog window.
void mousePressEvent(QMouseEvent *e) override
void resizeEvent(QResizeEvent *event) override
void changed()
Emitted when the shape's settings are changed.
QString dialogTitle() const
Returns the title for the symbol settings dialog window.
void setShape(const QgsLegendPatchShape &shape)
Sets the shape for the button.
void setPreviewSymbol(QgsSymbol *symbol)
Sets the symbol to use for previewing the legend patch shape.
~QgsLegendPatchShapeButton() override
void setMessageBar(QgsMessageBar *bar)
Sets the message bar associated with the widget.
void showEvent(QShowEvent *e) override
Widget for configuring a custom legend patch shape.
QgsLegendPatchShape shape() const
Returns the legend patch shape as currently defined by the widget.
void changed()
Emitted whenever the patch shape defined by the widget is changed.
Represents a patch shape for use in map legends.
bool isNull() const
Returns true if the patch shape is a null QgsLegendPatchShape, which indicates that the default legen...
Qgis::SymbolType symbolType() const
Returns the symbol type associated with this patch.
static QgsLineSymbol * createSimple(const QVariantMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties.
static QgsMarkerSymbol * createSimple(const QVariantMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
A bar for displaying non-blocking messages to the user.
Base class for any widget that can be shown as a inline panel.
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
static QgsPanelWidget * findParentPanel(QWidget *widget)
Traces through the parents of a widget to find if it is contained within a QgsPanelWidget widget.
void setPanelTitle(const QString &panelTitle)
Set the title of the panel when shown in the interface.
bool dockMode()
Returns the dock mode state.
Stores properties relating to a screen.
QgsLegendPatchShape defaultPatch(Qgis::SymbolType type, QSizeF size) const
Returns the default legend patch shape for the given symbol type.
@ LegendPatchShapeEntity
Legend patch shape.
Definition qgsstyle.h:210
static QgsStyle * defaultStyle(bool initialize=true)
Returns the default application-wide style.
Definition qgsstyle.cpp:146
QStringList symbolsOfFavorite(StyleEntity type) const
Returns the symbol names which are flagged as favorite.
QgsLegendPatchShape legendPatchShape(const QString &name) const
Returns the legend patch shape with the specified name.
static QPixmap symbolPreviewPixmap(const QgsSymbol *symbol, QSize size, int padding=0, QgsRenderContext *customContext=nullptr, bool selected=false, const QgsExpressionContext *expressionContext=nullptr, const QgsLegendPatchShape *shape=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Returns a pixmap preview for a color ramp.
static QIcon symbolPreviewIcon(const QgsSymbol *symbol, QSize size, int padding=0, QgsLegendPatchShape *shape=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Returns an icon preview for a color ramp.
Abstract base class for all rendered symbols.
Definition qgssymbol.h:231
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window's toolbar icons.
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly,...