1 /***************************************************************************
2 qgssymbolbutton.h
3 -----------------
4 Date : July 2017
5 Copyright : (C) 2017 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
16 #include "qgssymbolbutton.h"
17 #include "qgspanelwidget.h"
18 #include "qgsexpressioncontext.h"
19 #include "qgsexpressioncontextgenerator.h"
20 #include "qgsvectorlayer.h"
21 #include "qgssymbolselectordialog.h"
22 #include "qgsstyle.h"
23 #include "qgscolorwidgets.h"
24 #include "qgscolorschemeregistry.h"
25 #include "qgscolorswatchgrid.h"
26 #include "qgssymbollayerutils.h"
27 #include "qgsapplication.h"
28 #include "qgsguiutils.h"
29 #include "qgsexpressioncontextutils.h"
30 #include "qgsgui.h"
31 #include "qgscolordialog.h"
32
33 #include <QMenu>
34 #include <QClipboard>
35 #include <QDrag>
36
QgsSymbolButton(QWidget * parent,const QString & dialogTitle)37 QgsSymbolButton::QgsSymbolButton( QWidget *parent, const QString &dialogTitle )
38 : QToolButton( parent )
39 , mDialogTitle( dialogTitle.isEmpty() ? tr( "Symbol Settings" ) : dialogTitle )
40 {
41 mSymbol.reset( QgsFillSymbol::createSimple( QgsStringMap() ) );
42
43 setAcceptDrops( true );
44 connect( this, &QAbstractButton::clicked, this, &QgsSymbolButton::showSettingsDialog );
45
46 //setup dropdown menu
47 mMenu = new QMenu( this );
48 connect( mMenu, &QMenu::aboutToShow, this, &QgsSymbolButton::prepareMenu );
49 setMenu( mMenu );
50 setPopupMode( QToolButton::MenuButtonPopup );
51
52 //make sure height of button looks good under different platforms
53 QSize size = QToolButton::minimumSizeHint();
54 int fontHeight = static_cast< int >( Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 1.4 );
55 mSizeHint = QSize( size.width(), std::max( size.height(), fontHeight ) );
56 }
57
minimumSizeHint() const58 QSize QgsSymbolButton::minimumSizeHint() const
59 {
60
61 return mSizeHint;
62 }
63
sizeHint() const64 QSize QgsSymbolButton::sizeHint() const
65 {
66 return mSizeHint;
67 }
68
setSymbolType(QgsSymbol::SymbolType type)69 void QgsSymbolButton::setSymbolType( QgsSymbol::SymbolType type )
70 {
71 if ( type != mType )
72 {
73 switch ( type )
74 {
75 case QgsSymbol::Marker:
76 mSymbol.reset( QgsMarkerSymbol::createSimple( QgsStringMap() ) );
77 break;
78
79 case QgsSymbol::Line:
80 mSymbol.reset( QgsLineSymbol::createSimple( QgsStringMap() ) );
81 break;
82
83 case QgsSymbol::Fill:
84 mSymbol.reset( QgsFillSymbol::createSimple( QgsStringMap() ) );
85 break;
86
87 case QgsSymbol::Hybrid:
88 break;
89 }
90 }
91 updatePreview();
92 mType = type;
93 }
94
showSettingsDialog()95 void QgsSymbolButton::showSettingsDialog()
96 {
97 QgsExpressionContext context;
98 if ( mExpressionContextGenerator )
99 context = mExpressionContextGenerator->createExpressionContext();
100 else
101 {
102 context.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( mLayer.data() ) );
103 }
104 QgsSymbol *newSymbol = mSymbol->clone();
105
106 QgsSymbolWidgetContext symbolContext;
107 symbolContext.setExpressionContext( &context );
108 symbolContext.setMapCanvas( mMapCanvas );
109 symbolContext.setMessageBar( mMessageBar );
110
111 QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
112 if ( panel && panel->dockMode() )
113 {
114 QgsSymbolSelectorWidget *d = new QgsSymbolSelectorWidget( newSymbol, QgsStyle::defaultStyle(), mLayer, panel );
115 d->setPanelTitle( mDialogTitle );
116 d->setContext( symbolContext );
117 connect( d, &QgsPanelWidget::widgetChanged, this, &QgsSymbolButton::updateSymbolFromWidget );
118 connect( d, &QgsPanelWidget::panelAccepted, this, &QgsSymbolButton::cleanUpSymbolSelector );
119 panel->openPanel( d );
120 }
121 else
122 {
123 QgsSymbolSelectorDialog dialog( newSymbol, QgsStyle::defaultStyle(), mLayer, this );
124 dialog.setWindowTitle( mDialogTitle );
125 dialog.setContext( symbolContext );
126 if ( dialog.exec() )
127 {
128 setSymbol( newSymbol );
129 }
130 else
131 {
132 delete newSymbol;
133 }
134
135 // reactivate button's window
136 activateWindow();
137 }
138 }
139
updateSymbolFromWidget()140 void QgsSymbolButton::updateSymbolFromWidget()
141 {
142 if ( QgsSymbolSelectorWidget *w = qobject_cast<QgsSymbolSelectorWidget *>( sender() ) )
143 setSymbol( w->symbol()->clone() );
144 }
145
cleanUpSymbolSelector(QgsPanelWidget * container)146 void QgsSymbolButton::cleanUpSymbolSelector( QgsPanelWidget *container )
147 {
148 QgsSymbolSelectorWidget *w = qobject_cast<QgsSymbolSelectorWidget *>( container );
149 if ( !w )
150 return;
151
152 delete w->symbol();
153 }
154
mapCanvas() const155 QgsMapCanvas *QgsSymbolButton::mapCanvas() const
156 {
157 return mMapCanvas;
158 }
159
setMapCanvas(QgsMapCanvas * mapCanvas)160 void QgsSymbolButton::setMapCanvas( QgsMapCanvas *mapCanvas )
161 {
162 mMapCanvas = mapCanvas;
163 }
164
setMessageBar(QgsMessageBar * bar)165 void QgsSymbolButton::setMessageBar( QgsMessageBar *bar )
166 {
167 mMessageBar = bar;
168 }
169
messageBar() const170 QgsMessageBar *QgsSymbolButton::messageBar() const
171 {
172 return mMessageBar;
173 }
174
layer() const175 QgsVectorLayer *QgsSymbolButton::layer() const
176 {
177 return mLayer;
178 }
179
setLayer(QgsVectorLayer * layer)180 void QgsSymbolButton::setLayer( QgsVectorLayer *layer )
181 {
182 mLayer = layer;
183 }
184
registerExpressionContextGenerator(QgsExpressionContextGenerator * generator)185 void QgsSymbolButton::registerExpressionContextGenerator( QgsExpressionContextGenerator *generator )
186 {
187 mExpressionContextGenerator = generator;
188 }
189
setSymbol(QgsSymbol * symbol)190 void QgsSymbolButton::setSymbol( QgsSymbol *symbol )
191 {
192 mSymbol.reset( symbol );
193 updatePreview();
194 emit changed();
195 }
196
setColor(const QColor & color)197 void QgsSymbolButton::setColor( const QColor &color )
198 {
199 QColor opaque = color;
200 opaque.setAlphaF( 1.0 );
201
202 if ( opaque == mSymbol->color() )
203 return;
204
205 mSymbol->setColor( opaque );
206 updatePreview();
207 emit changed();
208 }
209
copySymbol()210 void QgsSymbolButton::copySymbol()
211 {
212 QApplication::clipboard()->setMimeData( QgsSymbolLayerUtils::symbolToMimeData( mSymbol.get() ) );
213 }
214
pasteSymbol()215 void QgsSymbolButton::pasteSymbol()
216 {
217 std::unique_ptr< QgsSymbol > symbol( QgsSymbolLayerUtils::symbolFromMimeData( QApplication::clipboard()->mimeData() ) );
218 if ( symbol && symbol->type() == mType )
219 setSymbol( symbol.release() );
220 }
221
copyColor()222 void QgsSymbolButton::copyColor()
223 {
224 QApplication::clipboard()->setMimeData( QgsSymbolLayerUtils::colorToMimeData( mSymbol->color() ) );
225 }
226
pasteColor()227 void QgsSymbolButton::pasteColor()
228 {
229 QColor clipColor;
230 bool hasAlpha = false;
231 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor, hasAlpha ) )
232 {
233 //paste color
234 setColor( clipColor );
235 QgsRecentColorScheme::addRecentColor( clipColor );
236 }
237 }
238
mousePressEvent(QMouseEvent * e)239 void QgsSymbolButton::mousePressEvent( QMouseEvent *e )
240 {
241 if ( mPickingColor )
242 {
243 //don't show dialog if in color picker mode
244 e->accept();
245 return;
246 }
247
248 if ( e->button() == Qt::RightButton )
249 {
250 QToolButton::showMenu();
251 return;
252 }
253 else if ( e->button() == Qt::LeftButton )
254 {
255 mDragStartPosition = e->pos();
256 }
257 QToolButton::mousePressEvent( e );
258 }
259
mouseMoveEvent(QMouseEvent * e)260 void QgsSymbolButton::mouseMoveEvent( QMouseEvent *e )
261 {
262 if ( mPickingColor )
263 {
264 updatePreview( QgsGui::sampleColor( e->globalPos() ) );
265 e->accept();
266 return;
267 }
268
269 //handle dragging colors/symbols from button
270
271 if ( !( e->buttons() & Qt::LeftButton ) )
272 {
273 //left button not depressed, so not a drag
274 QToolButton::mouseMoveEvent( e );
275 return;
276 }
277
278 if ( ( e->pos() - mDragStartPosition ).manhattanLength() < QApplication::startDragDistance() )
279 {
280 //mouse not moved, so not a drag
281 QToolButton::mouseMoveEvent( e );
282 return;
283 }
284
285 //user is dragging
286 QDrag *drag = new QDrag( this );
287 drag->setMimeData( QgsSymbolLayerUtils::colorToMimeData( mSymbol->color() ) );
288 drag->setPixmap( QgsColorWidget::createDragIcon( mSymbol->color() ) );
289 drag->exec( Qt::CopyAction );
290 setDown( false );
291 }
292
mouseReleaseEvent(QMouseEvent * e)293 void QgsSymbolButton::mouseReleaseEvent( QMouseEvent *e )
294 {
295 if ( mPickingColor )
296 {
297 //end color picking operation by sampling the color under cursor
298 stopPicking( e->globalPos() );
299 e->accept();
300 return;
301 }
302
303 QToolButton::mouseReleaseEvent( e );
304 }
305
keyPressEvent(QKeyEvent * e)306 void QgsSymbolButton::keyPressEvent( QKeyEvent *e )
307 {
308 if ( !mPickingColor )
309 {
310 //if not picking a color, use default tool button behavior
311 QToolButton::keyPressEvent( e );
312 return;
313 }
314
315 //cancel picking, sampling the color if space was pressed
316 stopPicking( QCursor::pos(), e->key() == Qt::Key_Space );
317 }
318
dragEnterEvent(QDragEnterEvent * e)319 void QgsSymbolButton::dragEnterEvent( QDragEnterEvent *e )
320 {
321 //is dragged data valid color data?
322 QColor mimeColor;
323 bool hasAlpha = false;
324
325 if ( colorFromMimeData( e->mimeData(), mimeColor, hasAlpha ) )
326 {
327 //if so, we accept the drag, and temporarily change the button's color
328 //to match the dragged color. This gives immediate feedback to the user
329 //that colors can be dropped here
330 e->acceptProposedAction();
331 updatePreview( mimeColor );
332 }
333 }
334
dragLeaveEvent(QDragLeaveEvent * e)335 void QgsSymbolButton::dragLeaveEvent( QDragLeaveEvent *e )
336 {
337 Q_UNUSED( e )
338 //reset button color
339 updatePreview();
340 }
341
dropEvent(QDropEvent * e)342 void QgsSymbolButton::dropEvent( QDropEvent *e )
343 {
344 //is dropped data valid format data?
345 QColor mimeColor;
346 bool hasAlpha = false;
347 if ( colorFromMimeData( e->mimeData(), mimeColor, hasAlpha ) )
348 {
349 //accept drop and set new color
350 e->acceptProposedAction();
351 mimeColor.setAlphaF( 1.0 );
352 mSymbol->setColor( mimeColor );
353 QgsRecentColorScheme::addRecentColor( mimeColor );
354 updatePreview();
355 emit changed();
356 }
357 updatePreview();
358 }
359
prepareMenu()360 void QgsSymbolButton::prepareMenu()
361 {
362 //we need to tear down and rebuild this menu every time it is shown. Otherwise the space allocated to any
363 //QgsColorSwatchGridAction is not recalculated by Qt and the swatch grid may not be the correct size
364 //for the number of colors shown in the grid. Note that we MUST refresh color swatch grids every time this
365 //menu is opened, otherwise color schemes like the recent color scheme grid are meaningless
366 mMenu->clear();
367
368 QAction *configureAction = new QAction( tr( "Configure Symbol…" ), this );
369 mMenu->addAction( configureAction );
370 connect( configureAction, &QAction::triggered, this, &QgsSymbolButton::showSettingsDialog );
371
372 QAction *copySymbolAction = new QAction( tr( "Copy Symbol" ), this );
373 mMenu->addAction( copySymbolAction );
374 connect( copySymbolAction, &QAction::triggered, this, &QgsSymbolButton::copySymbol );
375 QAction *pasteSymbolAction = new QAction( tr( "Paste Symbol" ), this );
376 //enable or disable paste action based on current clipboard contents. We always show the paste
377 //action, even if it's disabled, to give hint to the user that pasting symbols is possible
378 std::unique_ptr< QgsSymbol > tempSymbol( QgsSymbolLayerUtils::symbolFromMimeData( QApplication::clipboard()->mimeData() ) );
379 if ( tempSymbol && tempSymbol->type() == mType )
380 {
381 const int iconSize = QgsGuiUtils::scaleIconSize( 16 );
382 pasteSymbolAction->setIcon( QgsSymbolLayerUtils::symbolPreviewIcon( tempSymbol.get(), QSize( iconSize, iconSize ), 1 ) );
383 }
384 else
385 {
386 pasteSymbolAction->setEnabled( false );
387 }
388 mMenu->addAction( pasteSymbolAction );
389 connect( pasteSymbolAction, &QAction::triggered, this, &QgsSymbolButton::pasteSymbol );
390
391 mMenu->addSeparator();
392
393 QgsColorWheel *colorWheel = new QgsColorWheel( mMenu );
394 colorWheel->setColor( mSymbol->color() );
395 QgsColorWidgetAction *colorAction = new QgsColorWidgetAction( colorWheel, mMenu, mMenu );
396 colorAction->setDismissOnColorSelection( false );
397 connect( colorAction, &QgsColorWidgetAction::colorChanged, this, &QgsSymbolButton::setColor );
398 mMenu->addAction( colorAction );
399
400 QgsColorRampWidget *alphaRamp = new QgsColorRampWidget( mMenu, QgsColorWidget::Alpha, QgsColorRampWidget::Horizontal );
401 QColor alphaColor = mSymbol->color();
402 alphaColor.setAlphaF( mSymbol->opacity() );
403 alphaRamp->setColor( alphaColor );
404 QgsColorWidgetAction *alphaAction = new QgsColorWidgetAction( alphaRamp, mMenu, mMenu );
405 alphaAction->setDismissOnColorSelection( false );
406 connect( alphaAction, &QgsColorWidgetAction::colorChanged, this, [ = ]( const QColor & color )
407 {
408 double opacity = color.alphaF();
409 mSymbol->setOpacity( opacity );
410 updatePreview();
411 emit changed();
412 } );
413 connect( colorAction, &QgsColorWidgetAction::colorChanged, alphaRamp, [alphaRamp]( const QColor & color ) { alphaRamp->setColor( color, false ); }
414 );
415 mMenu->addAction( alphaAction );
416
417 //get schemes with ShowInColorButtonMenu flag set
418 QList< QgsColorScheme * > schemeList = QgsApplication::colorSchemeRegistry()->schemes( QgsColorScheme::ShowInColorButtonMenu );
419 QList< QgsColorScheme * >::iterator it = schemeList.begin();
420 for ( ; it != schemeList.end(); ++it )
421 {
422 QgsColorSwatchGridAction *colorAction = new QgsColorSwatchGridAction( *it, mMenu, QStringLiteral( "symbology" ), this );
423 colorAction->setBaseColor( mSymbol->color() );
424 mMenu->addAction( colorAction );
425 connect( colorAction, &QgsColorSwatchGridAction::colorChanged, this, &QgsSymbolButton::setColor );
426 connect( colorAction, &QgsColorSwatchGridAction::colorChanged, this, &QgsSymbolButton::addRecentColor );
427 }
428
429 mMenu->addSeparator();
430
431 QAction *copyColorAction = new QAction( tr( "Copy Color" ), this );
432 mMenu->addAction( copyColorAction );
433 connect( copyColorAction, &QAction::triggered, this, &QgsSymbolButton::copyColor );
434
435 QAction *pasteColorAction = new QAction( tr( "Paste Color" ), this );
436 //enable or disable paste action based on current clipboard contents. We always show the paste
437 //action, even if it's disabled, to give hint to the user that pasting colors is possible
438 QColor clipColor;
439 bool hasAlpha = false;
440 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor, hasAlpha ) )
441 {
442 pasteColorAction->setIcon( createColorIcon( clipColor ) );
443 }
444 else
445 {
446 pasteColorAction->setEnabled( false );
447 }
448 mMenu->addAction( pasteColorAction );
449 connect( pasteColorAction, &QAction::triggered, this, &QgsSymbolButton::pasteColor );
450
451 QAction *pickColorAction = new QAction( tr( "Pick Color" ), this );
452 mMenu->addAction( pickColorAction );
453 connect( pickColorAction, &QAction::triggered, this, &QgsSymbolButton::activatePicker );
454
455 QAction *chooseColorAction = new QAction( tr( "Choose Color…" ), this );
456 mMenu->addAction( chooseColorAction );
457 connect( chooseColorAction, &QAction::triggered, this, &QgsSymbolButton::showColorDialog );
458 }
459
addRecentColor(const QColor & color)460 void QgsSymbolButton::addRecentColor( const QColor &color )
461 {
462 QgsRecentColorScheme::addRecentColor( color );
463 }
464
activatePicker()465 void QgsSymbolButton::activatePicker()
466 {
467 //activate picker color
468 QApplication::setOverrideCursor( QgsApplication::getThemeCursor( QgsApplication::Cursor::Sampler ) );
469 grabMouse();
470 grabKeyboard();
471 mPickingColor = true;
472 setMouseTracking( true );
473 }
474
475
changeEvent(QEvent * e)476 void QgsSymbolButton::changeEvent( QEvent *e )
477 {
478 if ( e->type() == QEvent::EnabledChange )
479 {
480 updatePreview();
481 }
482 QToolButton::changeEvent( e );
483 }
484
showEvent(QShowEvent * e)485 void QgsSymbolButton::showEvent( QShowEvent *e )
486 {
487 updatePreview();
488 QToolButton::showEvent( e );
489 }
490
resizeEvent(QResizeEvent * event)491 void QgsSymbolButton::resizeEvent( QResizeEvent *event )
492 {
493 QToolButton::resizeEvent( event );
494 //recalculate icon size and redraw icon
495 mIconSize = QSize();
496 updatePreview();
497 }
498
updatePreview(const QColor & color,QgsSymbol * tempSymbol)499 void QgsSymbolButton::updatePreview( const QColor &color, QgsSymbol *tempSymbol )
500 {
501 std::unique_ptr< QgsSymbol > previewSymbol;
502
503 if ( tempSymbol )
504 previewSymbol.reset( tempSymbol->clone() );
505 else
506 previewSymbol.reset( mSymbol->clone() );
507
508 if ( color.isValid() )
509 previewSymbol->setColor( color );
510
511 QSize currentIconSize;
512 //icon size is button size with a small margin
513 if ( menu() )
514 {
515 if ( !mIconSize.isValid() )
516 {
517 //calculate size of push button part of widget (ie, without the menu dropdown button part)
518 QStyleOptionToolButton opt;
519 initStyleOption( &opt );
520 QRect buttonSize = QApplication::style()->subControlRect( QStyle::CC_ToolButton, &opt, QStyle::SC_ToolButton,
521 this );
522 //make sure height of icon looks good under different platforms
523 #ifdef Q_OS_WIN
524 mIconSize = QSize( buttonSize.width() - 10, height() - 6 );
525 #else
526 mIconSize = QSize( buttonSize.width() - 10, height() - 12 );
527 #endif
528 }
529 currentIconSize = mIconSize;
530 }
531 else
532 {
533 //no menu
534 #ifdef Q_OS_WIN
535 currentIconSize = QSize( width() - 10, height() - 6 );
536 #else
537 currentIconSize = QSize( width() - 10, height() - 12 );
538 #endif
539 }
540
541 if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
542 {
543 return;
544 }
545
546 //create an icon pixmap
547 QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( previewSymbol.get(), currentIconSize );
548 setIconSize( currentIconSize );
549 setIcon( icon );
550
551 // set tooltip
552 // create very large preview image
553
554 #if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
555 int width = static_cast< int >( Qgis::UI_SCALE_FACTOR * fontMetrics().width( 'X' ) * 23 );
556 #else
557 int width = static_cast< int >( Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 23 );
558 #endif
559 int height = static_cast< int >( width / 1.61803398875 ); // golden ratio
560
561 QPixmap pm = QgsSymbolLayerUtils::symbolPreviewPixmap( previewSymbol.get(), QSize( width, height ), height / 20 );
562 QByteArray data;
563 QBuffer buffer( &data );
564 pm.save( &buffer, "PNG", 100 );
565 setToolTip( QStringLiteral( "<img src='data:image/png;base64, %3'>" ).arg( QString( data.toBase64() ) ) );
566 }
567
colorFromMimeData(const QMimeData * mimeData,QColor & resultColor,bool & hasAlpha)568 bool QgsSymbolButton::colorFromMimeData( const QMimeData *mimeData, QColor &resultColor, bool &hasAlpha )
569 {
570 hasAlpha = false;
571 QColor mimeColor = QgsSymbolLayerUtils::colorFromMimeData( mimeData, hasAlpha );
572
573 if ( mimeColor.isValid() )
574 {
575 resultColor = mimeColor;
576 return true;
577 }
578
579 //could not get color from mime data
580 return false;
581 }
582
createColorIcon(const QColor & color) const583 QPixmap QgsSymbolButton::createColorIcon( const QColor &color ) const
584 {
585 //create an icon pixmap
586 const int iconSize = QgsGuiUtils::scaleIconSize( 16 );
587 QPixmap pixmap( iconSize, iconSize );
588 pixmap.fill( Qt::transparent );
589
590 QPainter p;
591 p.begin( &pixmap );
592
593 //draw color over pattern
594 p.setBrush( QBrush( color ) );
595
596 //draw border
597 p.setPen( QColor( 197, 197, 197 ) );
598 p.drawRect( 0, 0, iconSize - 1, iconSize - 1 );
599 p.end();
600 return pixmap;
601 }
602
stopPicking(QPoint eventPos,bool samplingColor)603 void QgsSymbolButton::stopPicking( QPoint eventPos, bool samplingColor )
604 {
605 //release mouse and keyboard, and reset cursor
606 releaseMouse();
607 releaseKeyboard();
608 QgsApplication::restoreOverrideCursor();
609 setMouseTracking( false );
610 mPickingColor = false;
611
612 if ( !samplingColor )
613 {
614 //not sampling color, restore old icon
615 updatePreview();
616 return;
617 }
618
619 const QColor newColor = QgsGui::sampleColor( eventPos );
620 setColor( newColor );
621 addRecentColor( newColor );
622 }
623
showColorDialog()624 void QgsSymbolButton::showColorDialog()
625 {
626 QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
627 if ( panel && panel->dockMode() )
628 {
629 QColor currentColor = mSymbol->color();
630 QgsCompoundColorWidget *colorWidget = new QgsCompoundColorWidget( panel, currentColor, QgsCompoundColorWidget::LayoutVertical );
631 colorWidget->setPanelTitle( tr( "Symbol Color" ) );
632 colorWidget->setAllowOpacity( true );
633
634 if ( currentColor.isValid() )
635 {
636 colorWidget->setPreviousColor( currentColor );
637 }
638
639 connect( colorWidget, &QgsCompoundColorWidget::currentColorChanged, this, [ = ]( const QColor & newColor )
640 {
641 if ( newColor.isValid() )
642 {
643 setColor( newColor );
644 }
645 } );
646 panel->openPanel( colorWidget );
647 return;
648 }
649
650 QgsColorDialog dialog( this, Qt::WindowFlags(), mSymbol->color() );
651 dialog.setTitle( tr( "Symbol Color" ) );
652 dialog.setAllowOpacity( true );
653
654 if ( dialog.exec() && dialog.color().isValid() )
655 {
656 setColor( dialog.color() );
657 }
658
659 // reactivate button's window
660 activateWindow();
661 }
662
setDialogTitle(const QString & title)663 void QgsSymbolButton::setDialogTitle( const QString &title )
664 {
665 mDialogTitle = title;
666 }
667
dialogTitle() const668 QString QgsSymbolButton::dialogTitle() const
669 {
670 return mDialogTitle;
671 }
672
symbol()673 QgsSymbol *QgsSymbolButton::symbol()
674 {
675 return mSymbol.get();
676 }
677