QGIS API Documentation 3.99.0-Master (26c88405ac0)
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
18#include "qgis.h"
19#include "qgsfillsymbol.h"
20#include "qgsguiutils.h"
22#include "qgslinesymbol.h"
23#include "qgsmarkersymbol.h"
24
25#include <QBuffer>
26#include <QMenu>
27
28#include "moc_qgslegendpatchshapebutton.cpp"
29
31 : QToolButton( parent )
32 , mShape( QgsStyle::defaultStyle()->defaultPatch( Qgis::SymbolType::Fill, QSizeF( 10, 5 ) ) )
33 , mDialogTitle( dialogTitle.isEmpty() ? tr( "Legend Patch Shape" ) : dialogTitle )
34{
35 mPreviewSymbol = QgsFillSymbol::createSimple( QVariantMap() );
36
37 connect( this, &QAbstractButton::clicked, this, &QgsLegendPatchShapeButton::showSettingsDialog );
38
39 //setup dropdown menu
40 mMenu = new QMenu( this );
41 connect( mMenu, &QMenu::aboutToShow, this, &QgsLegendPatchShapeButton::prepareMenu );
42 setMenu( mMenu );
43 setPopupMode( QToolButton::MenuButtonPopup );
44
45 //make sure height of button looks good under different platforms
46 QSize size = QToolButton::minimumSizeHint();
47 int fontHeight = static_cast<int>( Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 2.0 );
48 mSizeHint = QSize( size.width(), std::max( size.height(), fontHeight ) );
49}
50
52
54{
55 return mSizeHint;
56}
57
59{
60 return mSizeHint;
61}
62
64{
65 if ( mPreviewSymbol->type() != type )
66 {
67 switch ( type )
68 {
70 mPreviewSymbol = QgsMarkerSymbol::createSimple( QVariantMap() );
71 break;
72
74 mPreviewSymbol = QgsLineSymbol::createSimple( QVariantMap() );
75 break;
76
78 mPreviewSymbol = QgsFillSymbol::createSimple( QVariantMap() );
79 break;
80
82 break;
83 }
84 }
85
86 if ( type != mType )
87 {
88 mType = type;
90 }
91
92 updatePreview();
93}
94
96{
97 mPreviewSymbol.reset( symbol );
98 updatePreview();
99}
100
101void QgsLegendPatchShapeButton::showSettingsDialog()
102{
104 if ( panel && panel->dockMode() )
105 {
106 QgsLegendPatchShapeWidget *widget = new QgsLegendPatchShapeWidget( this, mShape );
107 connect( widget, &QgsLegendPatchShapeWidget::changed, this, [this, widget] {
108 setShape( widget->shape() );
109 } );
110 widget->setPanelTitle( mDialogTitle );
111 panel->openPanel( widget );
112 }
113}
114
116{
117 switch ( mType )
118 {
120 mShape = QgsStyle::defaultStyle()->defaultPatch( Qgis::SymbolType::Marker, QSizeF( 10, 5 ) );
121 break;
122
124 mShape = QgsStyle::defaultStyle()->defaultPatch( Qgis::SymbolType::Line, QSizeF( 10, 5 ) );
125 break;
126
128 mShape = QgsStyle::defaultStyle()->defaultPatch( Qgis::SymbolType::Fill, QSizeF( 10, 5 ) );
129 break;
130
132 break;
133 }
134 mIsDefault = true;
135 updatePreview();
136 emit changed();
137}
138
140{
141 mMessageBar = bar;
142}
143
145{
146 return mMessageBar;
147}
148
150{
151 mShape = shape.symbolType() == mType ? shape : QgsLegendPatchShape();
152 mIsDefault = mShape.isNull();
153 if ( mIsDefault )
154 {
155 switch ( mType )
156 {
158 mShape = QgsStyle::defaultStyle()->defaultPatch( Qgis::SymbolType::Marker, QSizeF( 10, 5 ) );
159 break;
160
162 mShape = QgsStyle::defaultStyle()->defaultPatch( Qgis::SymbolType::Line, QSizeF( 10, 5 ) );
163 break;
164
166 mShape = QgsStyle::defaultStyle()->defaultPatch( Qgis::SymbolType::Fill, QSizeF( 10, 5 ) );
167 break;
168
170 break;
171 }
172 }
173
174 updatePreview();
175 emit changed();
176}
177
179{
180 if ( e->button() == Qt::RightButton )
181 {
182 QToolButton::showMenu();
183 return;
184 }
185 QToolButton::mousePressEvent( e );
186}
187
188void QgsLegendPatchShapeButton::prepareMenu()
189{
190 mMenu->clear();
191
192 QAction *configureAction = new QAction( tr( "Configure Patch…" ), this );
193 mMenu->addAction( configureAction );
194 connect( configureAction, &QAction::triggered, this, &QgsLegendPatchShapeButton::showSettingsDialog );
195
196 QAction *defaultAction = new QAction( tr( "Reset to Default" ), this );
197 mMenu->addAction( defaultAction );
198 connect( defaultAction, &QAction::triggered, this, [this] { setToDefault(); emit changed(); } );
199
200 mMenu->addSeparator();
201
203 patchNames.sort();
204 const int iconSize = QgsGuiUtils::scaleIconSize( 16 );
205 for ( const QString &name : std::as_const( patchNames ) )
206 {
207 const QgsLegendPatchShape shape = QgsStyle::defaultStyle()->legendPatchShape( name );
208 if ( shape.symbolType() == mType )
209 {
210 if ( const QgsSymbol *symbol = QgsStyle::defaultStyle()->previewSymbolForPatchShape( shape ) )
211 {
212 QIcon icon = QgsSymbolLayerUtils::symbolPreviewPixmap( symbol, QSize( iconSize, iconSize ), 1, nullptr, false, nullptr, &shape, QgsScreenProperties( screen() ) );
213 QAction *action = new QAction( name, this );
214 action->setIcon( icon );
215 connect( action, &QAction::triggered, this, [this, name] { loadPatchFromStyle( name ); } );
216 mMenu->addAction( action );
217 }
218 }
219 }
220}
221
222void QgsLegendPatchShapeButton::loadPatchFromStyle( const QString &name )
223{
224 if ( !QgsStyle::defaultStyle()->legendPatchShapeNames().contains( name ) )
225 return;
226
227 const QgsLegendPatchShape newShape = QgsStyle::defaultStyle()->legendPatchShape( name );
228 setShape( newShape );
229}
230
232{
233 if ( e->type() == QEvent::EnabledChange )
234 {
235 updatePreview();
236 }
237 QToolButton::changeEvent( e );
238}
239
241{
242 updatePreview();
243 QToolButton::showEvent( e );
244}
245
246void QgsLegendPatchShapeButton::resizeEvent( QResizeEvent *event )
247{
248 QToolButton::resizeEvent( event );
249 //recalculate icon size and redraw icon
250 mIconSize = QSize();
251 updatePreview();
252}
253
254void QgsLegendPatchShapeButton::updatePreview()
255{
256 QSize currentIconSize;
257 //icon size is button size with a small margin
258 if ( menu() )
259 {
260 if ( !mIconSize.isValid() )
261 {
262 //calculate size of push button part of widget (ie, without the menu dropdown button part)
263 QStyleOptionToolButton opt;
264 initStyleOption( &opt );
265 QRect buttonSize = QApplication::style()->subControlRect( QStyle::CC_ToolButton, &opt, QStyle::SC_ToolButton, this );
266 //make sure height of icon looks good under different platforms
267#ifdef Q_OS_WIN
268 mIconSize = QSize( buttonSize.width() - 10, height() - 6 );
269#else
270 mIconSize = QSize( buttonSize.width() - 10, height() - 12 );
271#endif
272 }
273 currentIconSize = mIconSize;
274 }
275 else
276 {
277 //no menu
278#ifdef Q_OS_WIN
279 currentIconSize = QSize( width() - 10, height() - 6 );
280#else
281 currentIconSize = QSize( width() - 10, height() - 12 );
282#endif
283 }
284
285 if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
286 {
287 return;
288 }
289
290 //create an icon pixmap
291 QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mPreviewSymbol.get(), currentIconSize, currentIconSize.height() / 10, &mShape, QgsScreenProperties( screen() ) );
292 setIconSize( currentIconSize );
293 setIcon( icon );
294
295 // set tooltip
296 // create very large preview image
297
298 int width = static_cast<int>( Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 23 );
299 int height = static_cast<int>( width / 1.61803398875 ); // golden ratio
300
301 QPixmap pm = QgsSymbolLayerUtils::symbolPreviewPixmap( mPreviewSymbol.get(), QSize( width, height ), height / 20, nullptr, false, nullptr, &mShape, QgsScreenProperties( screen() ) );
302 QByteArray data;
303 QBuffer buffer( &data );
304 pm.save( &buffer, "PNG", 100 );
305 setToolTip( QStringLiteral( "<img src='data:image/png;base64, %3' width=\"%4\">" ).arg( QString( data.toBase64() ) ).arg( width ) );
306}
307
309{
310 mDialogTitle = title;
311}
312
314{
315 return mDialogTitle;
316}
317
319{
320 return mIsDefault ? QgsLegendPatchShape() : mShape;
321}
Provides global constants and enumerations for use throughout the application.
Definition qgis.h:56
SymbolType
Symbol types.
Definition qgis.h:610
@ Marker
Marker symbol.
Definition qgis.h:611
@ Line
Line symbol.
Definition qgis.h:612
@ Fill
Fill symbol.
Definition qgis.h:613
@ Hybrid
Hybrid symbol.
Definition qgis.h:614
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition qgis.h:6222
static std::unique_ptr< 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.
static std::unique_ptr< QgsLineSymbol > createSimple(const QVariantMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties.
static std::unique_ptr< 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 an 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 ...
bool dockMode() const
Returns the dock mode state.
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.
A database of saved style entities, including symbols, color ramps, text formats and others.
Definition qgsstyle.h:88
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:211
static QgsStyle * defaultStyle(bool initialize=true)
Returns the default application-wide style.
Definition qgsstyle.cpp:147
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,...