QGIS API Documentation 3.99.0-Master (21b3aa880ba)
Loading...
Searching...
No Matches
qgssymbolbutton.cpp
Go to the documentation of this file.
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
18#include "qgsapplication.h"
19#include "qgscolordialog.h"
21#include "qgscolorswatchgrid.h"
22#include "qgscolorwidgets.h"
26#include "qgsfillsymbol.h"
27#include "qgsgui.h"
28#include "qgsguiutils.h"
29#include "qgslinesymbol.h"
30#include "qgsmarkersymbol.h"
31#include "qgspanelwidget.h"
32#include "qgsstyle.h"
33#include "qgssymbollayerutils.h"
35#include "qgsvectorlayer.h"
36
37#include <QBuffer>
38#include <QClipboard>
39#include <QDrag>
40#include <QMenu>
41
42#include "moc_qgssymbolbutton.cpp"
43
44QgsSymbolButton::QgsSymbolButton( QWidget *parent, const QString &dialogTitle )
45 : QToolButton( parent )
46 , mDialogTitle( dialogTitle.isEmpty() ? tr( "Symbol Settings" ) : dialogTitle )
47{
48 mSymbol = QgsFillSymbol::createSimple( QVariantMap() );
49
50 setAcceptDrops( true );
51 connect( this, &QAbstractButton::clicked, this, &QgsSymbolButton::showSettingsDialog );
52
53 //setup dropdown menu
54 mMenu = new QMenu( this );
55 connect( mMenu, &QMenu::aboutToShow, this, &QgsSymbolButton::prepareMenu );
56 setMenu( mMenu );
57 setPopupMode( QToolButton::MenuButtonPopup );
58
59 updateSizeHint();
60}
61
62void QgsSymbolButton::updateSizeHint()
63{
64 //make sure height of button looks good under different platforms
65 const QSize size = QToolButton::minimumSizeHint();
66 const int fontHeight = static_cast<int>( Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 1.4 );
67 switch ( mType )
68 {
70 if ( mFixedSizeConstraints )
71 {
72 if ( mSymbol )
73 {
74 mSizeHint = QSize( size.width(), std::max( size.height(), fontHeight * 3 ) );
75 setMaximumWidth( mSizeHint.height() * 1.5 );
76 setMinimumWidth( maximumWidth() );
77 }
78 else
79 {
80 mSizeHint = QSize( size.width(), fontHeight );
81 setMaximumWidth( 999999 );
82 mSizeHint.setWidth( QToolButton::sizeHint().width() );
83 }
84 }
85 else
86 {
87 setMaximumWidth( 999999 );
88 mSizeHint = QSize( size.width(), std::max( size.height(), fontHeight ) );
89 }
90 break;
91
95 mSizeHint = QSize( size.width(), std::max( size.height(), fontHeight ) );
96 break;
97 }
98
99 setMinimumHeight( mSizeHint.height() );
100
101 updateGeometry();
102}
103
105
107{
108 return mSizeHint;
109}
110
112{
113 return mSizeHint;
114}
115
117{
118 if ( type != mType )
119 {
120 switch ( type )
121 {
123 mSymbol = QgsMarkerSymbol::createSimple( QVariantMap() );
124 break;
125
127 mSymbol = QgsLineSymbol::createSimple( QVariantMap() );
128 break;
129
131 mSymbol = QgsFillSymbol::createSimple( QVariantMap() );
132 break;
133
135 break;
136 }
137 }
138 mType = type;
139 updateSizeHint();
140 updatePreview();
141}
142
143void QgsSymbolButton::showSettingsDialog()
144{
145 QgsExpressionContext context;
146 if ( mExpressionContextGenerator )
147 context = mExpressionContextGenerator->createExpressionContext();
148 else
149 {
151 }
152
153 std::unique_ptr<QgsSymbol> newSymbol;
154 if ( mSymbol )
155 {
156 newSymbol.reset( mSymbol->clone() );
157 }
158 else
159 {
160 switch ( mType )
161 {
164 break;
167 break;
170 break;
172 break;
173 }
174 }
175
176 QgsSymbolWidgetContext symbolContext;
177 symbolContext.setExpressionContext( &context );
178 symbolContext.setMapCanvas( mMapCanvas );
179 symbolContext.setMessageBar( mMessageBar );
180
181 QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
182 if ( panel && panel->dockMode() )
183 {
184 QgsSymbolSelectorWidget *widget = QgsSymbolSelectorWidget::createWidgetWithSymbolOwnership( std::move( newSymbol ), QgsStyle::defaultStyle(), mLayer, panel );
185 widget->setPanelTitle( mDialogTitle );
186 widget->setContext( symbolContext );
187 connect( widget, &QgsPanelWidget::widgetChanged, this, [this, widget] { updateSymbolFromWidget( widget ); } );
188 panel->openPanel( widget );
189 }
190 else
191 {
192 QgsSymbolSelectorDialog dialog( newSymbol.get(), QgsStyle::defaultStyle(), mLayer, this );
193 dialog.setWindowTitle( mDialogTitle );
194 dialog.setContext( symbolContext );
195 if ( dialog.exec() )
196 {
197 setSymbol( newSymbol.release() );
198 }
199
200 // reactivate button's window
201 activateWindow();
202 }
203}
204
205void QgsSymbolButton::updateSymbolFromWidget( QgsSymbolSelectorWidget *widget )
206{
207 setSymbol( widget->symbol()->clone() );
208}
209
211{
212 return mMapCanvas;
213}
214
219
221{
222 mMessageBar = bar;
223}
224
226{
227 return mMessageBar;
228}
229
231{
232 return mLayer;
233}
234
236{
237 mLayer = layer;
238}
239
241{
242 mExpressionContextGenerator = generator;
243}
244
246{
247 mDefaultSymbol.reset( symbol );
248}
249
251{
252 return mDefaultSymbol.get();
253}
254
256{
257 mSymbol.reset( symbol );
258 updateSizeHint();
259 updatePreview();
260 emit changed();
261}
262
263void QgsSymbolButton::setColor( const QColor &color )
264{
265 if ( !mSymbol )
266 return;
267
268 QColor opaque = color;
269 opaque.setAlphaF( 1.0 );
270
271 if ( opaque == mSymbol->color() )
272 return;
273
274 mSymbol->setColor( opaque );
275 updatePreview();
276 emit changed();
277}
278
280{
281 QApplication::clipboard()->setMimeData( QgsSymbolLayerUtils::symbolToMimeData( mSymbol.get() ) );
282}
283
285{
286 std::unique_ptr<QgsSymbol> symbol( QgsSymbolLayerUtils::symbolFromMimeData( QApplication::clipboard()->mimeData() ) );
287 if ( symbol && symbol->type() == mType )
288 setSymbol( symbol.release() );
289}
290
292{
293 QApplication::clipboard()->setMimeData( QgsSymbolLayerUtils::colorToMimeData( mSymbol->color() ) );
294}
295
297{
298 QColor clipColor;
299 bool hasAlpha = false;
300 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor, hasAlpha ) )
301 {
302 //paste color
303 setColor( clipColor );
305 }
306}
307
309{
310 if ( mPickingColor )
311 {
312 //don't show dialog if in color picker mode
313 e->accept();
314 return;
315 }
316
317 if ( e->button() == Qt::RightButton )
318 {
319 QToolButton::showMenu();
320 return;
321 }
322 else if ( e->button() == Qt::LeftButton )
323 {
324 mDragStartPosition = e->pos();
325 }
326 QToolButton::mousePressEvent( e );
327}
328
330{
331 if ( mPickingColor )
332 {
333 updatePreview( QgsGui::sampleColor( e->globalPos() ) );
334 e->accept();
335 return;
336 }
337
338 //handle dragging colors/symbols from button
339
340 if ( !( e->buttons() & Qt::LeftButton ) )
341 {
342 //left button not depressed, so not a drag
343 QToolButton::mouseMoveEvent( e );
344 return;
345 }
346
347 if ( ( e->pos() - mDragStartPosition ).manhattanLength() < QApplication::startDragDistance() )
348 {
349 //mouse not moved, so not a drag
350 QToolButton::mouseMoveEvent( e );
351 return;
352 }
353
354 //user is dragging
355 QDrag *drag = new QDrag( this );
356 drag->setMimeData( QgsSymbolLayerUtils::colorToMimeData( mSymbol->color() ) );
357 drag->setPixmap( QgsColorWidget::createDragIcon( mSymbol->color() ) );
358 drag->exec( Qt::CopyAction );
359 setDown( false );
360}
361
363{
364 if ( mPickingColor )
365 {
366 //end color picking operation by sampling the color under cursor
367 stopPicking( e->globalPos() );
368 e->accept();
369 return;
370 }
371
372 QToolButton::mouseReleaseEvent( e );
373}
374
376{
377 if ( !mPickingColor )
378 {
379 //if not picking a color, use default tool button behavior
380 QToolButton::keyPressEvent( e );
381 return;
382 }
383
384 //cancel picking, sampling the color if space was pressed
385 stopPicking( QCursor::pos(), e->key() == Qt::Key_Space );
386}
387
388void QgsSymbolButton::dragEnterEvent( QDragEnterEvent *e )
389{
390 //is dragged data valid color data?
391 QColor mimeColor;
392 bool hasAlpha = false;
393
394 if ( colorFromMimeData( e->mimeData(), mimeColor, hasAlpha ) )
395 {
396 //if so, we accept the drag, and temporarily change the button's color
397 //to match the dragged color. This gives immediate feedback to the user
398 //that colors can be dropped here
399 e->acceptProposedAction();
400 updatePreview( mimeColor );
401 }
402}
403
404void QgsSymbolButton::dragLeaveEvent( QDragLeaveEvent *e )
405{
406 Q_UNUSED( e )
407 //reset button color
408 updatePreview();
409}
410
411void QgsSymbolButton::dropEvent( QDropEvent *e )
412{
413 //is dropped data valid format data?
414 QColor mimeColor;
415 bool hasAlpha = false;
416 if ( colorFromMimeData( e->mimeData(), mimeColor, hasAlpha ) )
417 {
418 //accept drop and set new color
419 e->acceptProposedAction();
420 mimeColor.setAlphaF( 1.0 );
421 mSymbol->setColor( mimeColor );
423 updatePreview();
424 emit changed();
425 }
426 updatePreview();
427}
428
429void QgsSymbolButton::wheelEvent( QWheelEvent *event )
430{
431 if ( isEnabled() && mSymbol )
432 {
433 bool symbolChanged = false;
434 const double increment = ( ( event->modifiers() & Qt::ControlModifier ) ? 0.1 : 1 ) * ( event->angleDelta().y() > 0 ? 1 : -1 );
435 switch ( mSymbol->type() )
436 {
438 {
439 QgsMarkerSymbol *marker = qgis::down_cast<QgsMarkerSymbol *>( mSymbol.get() );
440 if ( marker )
441 {
442 const double size = std::max( 0.0, marker->size() + increment );
443 marker->setSize( size );
444 symbolChanged = true;
445 }
446 break;
447 }
448
450 {
451 QgsLineSymbol *line = qgis::down_cast<QgsLineSymbol *>( mSymbol.get() );
452 if ( line )
453 {
454 const double width = std::max( 0.0, line->width() + increment );
455 line->setWidth( width );
456 symbolChanged = true;
457 }
458 break;
459 }
460
463 break;
464 }
465
466 if ( symbolChanged )
467 {
468 updatePreview();
469 emit changed();
470 }
471
472 event->accept();
473 }
474 else
475 {
476 QToolButton::wheelEvent( event );
477 }
478}
479
480void QgsSymbolButton::prepareMenu()
481{
482 //we need to tear down and rebuild this menu every time it is shown. Otherwise the space allocated to any
483 //QgsColorSwatchGridAction is not recalculated by Qt and the swatch grid may not be the correct size
484 //for the number of colors shown in the grid. Note that we MUST refresh color swatch grids every time this
485 //menu is opened, otherwise color schemes like the recent color scheme grid are meaningless
486 mMenu->clear();
487
488 QAction *configureAction = new QAction( tr( "Configure Symbol…" ), this );
489 mMenu->addAction( configureAction );
490 connect( configureAction, &QAction::triggered, this, &QgsSymbolButton::showSettingsDialog );
491
492 QAction *copySymbolAction = new QAction( tr( "Copy Symbol" ), this );
493 copySymbolAction->setEnabled( !isNull() );
494 mMenu->addAction( copySymbolAction );
495 connect( copySymbolAction, &QAction::triggered, this, &QgsSymbolButton::copySymbol );
496
497 const int iconSize = QgsGuiUtils::scaleIconSize( 16 );
498
499 QAction *pasteSymbolAction = new QAction( tr( "Paste Symbol" ), this );
500 //enable or disable paste action based on current clipboard contents. We always show the paste
501 //action, even if it's disabled, to give hint to the user that pasting symbols is possible
502 std::unique_ptr<QgsSymbol> tempSymbol( QgsSymbolLayerUtils::symbolFromMimeData( QApplication::clipboard()->mimeData() ) );
503 if ( tempSymbol && tempSymbol->type() == mType )
504 {
505 pasteSymbolAction->setIcon( QgsSymbolLayerUtils::symbolPreviewIcon( tempSymbol.get(), QSize( iconSize, iconSize ), 1, nullptr, QgsScreenProperties( screen() ) ) );
506 }
507 else
508 {
509 pasteSymbolAction->setEnabled( false );
510 }
511 mMenu->addAction( pasteSymbolAction );
512 connect( pasteSymbolAction, &QAction::triggered, this, &QgsSymbolButton::pasteSymbol );
513
514 if ( mShowNull )
515 {
516 QAction *nullAction = new QAction( tr( "Clear Current Symbol" ), this );
517 nullAction->setEnabled( !isNull() );
518 mMenu->addAction( nullAction );
519 connect( nullAction, &QAction::triggered, this, &QgsSymbolButton::setToNull );
520 }
521
522 //show default symbol option if set
523 if ( mDefaultSymbol )
524 {
525 QAction *defaultSymbolAction = new QAction( tr( "Default Symbol" ), this );
526 defaultSymbolAction->setIcon( QgsSymbolLayerUtils::symbolPreviewIcon( mDefaultSymbol.get(), QSize( iconSize, iconSize ), 1, nullptr, QgsScreenProperties( screen() ) ) );
527 mMenu->addAction( defaultSymbolAction );
528 connect( defaultSymbolAction, &QAction::triggered, this, &QgsSymbolButton::setToDefaultSymbol );
529 }
530
531 if ( mSymbol )
532 {
533 mMenu->addSeparator();
534
535 QgsColorWheel *colorWheel = new QgsColorWheel( mMenu );
536 colorWheel->setColor( mSymbol->color() );
537 QgsColorWidgetAction *colorAction = new QgsColorWidgetAction( colorWheel, mMenu, mMenu );
538 colorAction->setDismissOnColorSelection( false );
539 connect( colorAction, &QgsColorWidgetAction::colorChanged, this, &QgsSymbolButton::setColor );
540 mMenu->addAction( colorAction );
541
542 QgsColorRampWidget *alphaRamp = new QgsColorRampWidget( mMenu, QgsColorWidget::Alpha, QgsColorRampWidget::Horizontal );
543 QColor alphaColor = mSymbol->color();
544 alphaColor.setAlphaF( mSymbol->opacity() );
545 alphaRamp->setColor( alphaColor );
546 QgsColorWidgetAction *alphaAction = new QgsColorWidgetAction( alphaRamp, mMenu, mMenu );
547 alphaAction->setDismissOnColorSelection( false );
548 connect( alphaAction, &QgsColorWidgetAction::colorChanged, this, [this]( const QColor &color ) {
549 const double opacity = color.alphaF();
550 mSymbol->setOpacity( opacity );
551 updatePreview();
552 emit changed();
553 } );
554 connect( colorAction, &QgsColorWidgetAction::colorChanged, alphaRamp, [alphaRamp]( const QColor &color ) { alphaRamp->setColor( color, false ); } );
555 mMenu->addAction( alphaAction );
556
557 //get schemes with ShowInColorButtonMenu flag set
559 QList<QgsColorScheme *>::iterator it = schemeList.begin();
560 for ( ; it != schemeList.end(); ++it )
561 {
562 QgsColorSwatchGridAction *colorAction = new QgsColorSwatchGridAction( *it, mMenu, QStringLiteral( "symbology" ), this );
563 colorAction->setBaseColor( mSymbol->color() );
564 mMenu->addAction( colorAction );
566 connect( colorAction, &QgsColorSwatchGridAction::colorChanged, this, &QgsSymbolButton::addRecentColor );
567 }
568
569 mMenu->addSeparator();
570
571 QAction *copyColorAction = new QAction( tr( "Copy Color" ), this );
572 mMenu->addAction( copyColorAction );
573 connect( copyColorAction, &QAction::triggered, this, &QgsSymbolButton::copyColor );
574
575 QAction *pasteColorAction = new QAction( tr( "Paste Color" ), this );
576 //enable or disable paste action based on current clipboard contents. We always show the paste
577 //action, even if it's disabled, to give hint to the user that pasting colors is possible
578 QColor clipColor;
579 bool hasAlpha = false;
580 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor, hasAlpha ) )
581 {
582 pasteColorAction->setIcon( createColorIcon( clipColor ) );
583 }
584 else
585 {
586 pasteColorAction->setEnabled( false );
587 }
588 mMenu->addAction( pasteColorAction );
589 connect( pasteColorAction, &QAction::triggered, this, &QgsSymbolButton::pasteColor );
590
591 QAction *pickColorAction = new QAction( tr( "Pick Color" ), this );
592 mMenu->addAction( pickColorAction );
593 connect( pickColorAction, &QAction::triggered, this, &QgsSymbolButton::activatePicker );
594
595 QAction *chooseColorAction = new QAction( tr( "Choose Color…" ), this );
596 mMenu->addAction( chooseColorAction );
597 connect( chooseColorAction, &QAction::triggered, this, &QgsSymbolButton::showColorDialog );
598 }
599}
600
601void QgsSymbolButton::addRecentColor( const QColor &color )
602{
604}
605
606void QgsSymbolButton::activatePicker()
607{
608 //activate picker color
609 QApplication::setOverrideCursor( QgsApplication::getThemeCursor( QgsApplication::Cursor::Sampler ) );
610 grabMouse();
611 grabKeyboard();
612 mPickingColor = true;
613 setMouseTracking( true );
614}
615
616
618{
619 if ( e->type() == QEvent::EnabledChange )
620 {
621 updatePreview();
622 }
623 QToolButton::changeEvent( e );
624}
625
626void QgsSymbolButton::showEvent( QShowEvent *e )
627{
628 updatePreview();
629 QToolButton::showEvent( e );
630}
631
632void QgsSymbolButton::resizeEvent( QResizeEvent *event )
633{
634 QToolButton::resizeEvent( event );
635 //recalculate icon size and redraw icon
636 mIconSize = QSize();
637 updatePreview();
638}
639
640void QgsSymbolButton::updatePreview( const QColor &color, QgsSymbol *tempSymbol )
641{
642 QSize currentIconSize;
643 //icon size is button size with a small margin
644 if ( menu() )
645 {
646 if ( !mIconSize.isValid() )
647 {
648 //calculate size of push button part of widget (ie, without the menu dropdown button part)
649 QStyleOptionToolButton opt;
650 initStyleOption( &opt );
651 const QRect buttonSize = QApplication::style()->subControlRect( QStyle::CC_ToolButton, &opt, QStyle::SC_ToolButton, this );
652 //make sure height of icon looks good under different platforms
653#ifdef Q_OS_WIN
654 mIconSize = QSize( buttonSize.width() - 10, height() - 6 );
655#else
656 mIconSize = QSize( buttonSize.width() - 10, height() - 12 );
657#endif
658 }
659 currentIconSize = mIconSize;
660 }
661 else
662 {
663 //no menu
664#ifdef Q_OS_WIN
665 currentIconSize = QSize( width() - 10, height() - 6 );
666#else
667 currentIconSize = QSize( width() - 10, height() - 12 );
668#endif
669 }
670
671 if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
672 {
673 return;
674 }
675
676 std::unique_ptr<QgsSymbol> previewSymbol;
677
678 if ( tempSymbol )
679 {
680 previewSymbol.reset( tempSymbol->clone() );
681 }
682 else if ( mSymbol )
683 {
684 previewSymbol.reset( mSymbol->clone() );
685 }
686 else
687 {
688 setIconSize( currentIconSize );
689 setIcon( QIcon() );
690 setToolTip( QString() );
691 return;
692 }
693
694 if ( color.isValid() )
695 previewSymbol->setColor( color );
696
697 //create an icon pixmap
698 const QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( previewSymbol.get(), currentIconSize, 0, nullptr, QgsScreenProperties( screen() ) );
699 setIconSize( currentIconSize );
700 setIcon( icon );
701
702 // set tooltip
703 // create very large preview image
704 const int width = static_cast<int>( Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 23 );
705 const int height = static_cast<int>( width / 1.61803398875 ); // golden ratio
706
707 const QPixmap pm = QgsSymbolLayerUtils::symbolPreviewPixmap( previewSymbol.get(), QSize( width, height ), height / 20, nullptr, false, nullptr, nullptr, QgsScreenProperties( screen() ) );
708 QByteArray data;
709 QBuffer buffer( &data );
710 pm.save( &buffer, "PNG", 100 );
711 setToolTip( QStringLiteral( "<img src='data:image/png;base64, %3' width=\"%4\">" ).arg( QString( data.toBase64() ) ).arg( width ) );
712}
713
714bool QgsSymbolButton::colorFromMimeData( const QMimeData *mimeData, QColor &resultColor, bool &hasAlpha )
715{
716 hasAlpha = false;
717 const QColor mimeColor = QgsSymbolLayerUtils::colorFromMimeData( mimeData, hasAlpha );
718
719 if ( mimeColor.isValid() )
720 {
721 resultColor = mimeColor;
722 return true;
723 }
724
725 //could not get color from mime data
726 return false;
727}
728
729QPixmap QgsSymbolButton::createColorIcon( const QColor &color ) const
730{
731 //create an icon pixmap
732 const int iconSize = QgsGuiUtils::scaleIconSize( 16 );
733 QPixmap pixmap( iconSize, iconSize );
734 pixmap.fill( Qt::transparent );
735
736 QPainter p;
737 p.begin( &pixmap );
738
739 //draw color over pattern
740 p.setBrush( QBrush( color ) );
741
742 //draw border
743 p.setPen( QColor( 197, 197, 197 ) );
744 p.drawRect( 0, 0, iconSize - 1, iconSize - 1 );
745 p.end();
746 return pixmap;
747}
748
749void QgsSymbolButton::stopPicking( QPoint eventPos, bool samplingColor )
750{
751 //release mouse and keyboard, and reset cursor
752 releaseMouse();
753 releaseKeyboard();
754 QgsApplication::restoreOverrideCursor();
755 setMouseTracking( false );
756 mPickingColor = false;
757
758 if ( !samplingColor )
759 {
760 //not sampling color, restore old icon
761 updatePreview();
762 return;
763 }
764
765 const QColor newColor = QgsGui::sampleColor( eventPos );
766 setColor( newColor );
767 addRecentColor( newColor );
768}
769
770void QgsSymbolButton::showColorDialog()
771{
772 if ( !mSymbol )
773 return;
774
775 QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
776 if ( panel && panel->dockMode() )
777 {
778 const QColor currentColor = mSymbol->color();
779 QgsCompoundColorWidget *colorWidget = new QgsCompoundColorWidget( panel, currentColor, QgsCompoundColorWidget::LayoutVertical );
780 colorWidget->setPanelTitle( tr( "Symbol Color" ) );
781 colorWidget->setAllowOpacity( true );
782
783 if ( currentColor.isValid() )
784 {
785 colorWidget->setPreviousColor( currentColor );
786 }
787
788 connect( colorWidget, &QgsCompoundColorWidget::currentColorChanged, this, [this]( const QColor &newColor ) {
789 if ( newColor.isValid() )
790 {
791 setColor( newColor );
792 }
793 } );
794 panel->openPanel( colorWidget );
795 return;
796 }
797
798 QgsColorDialog dialog( this, Qt::WindowFlags(), mSymbol->color() );
799 dialog.setTitle( tr( "Symbol Color" ) );
800 dialog.setAllowOpacity( true );
801
802 if ( dialog.exec() && dialog.color().isValid() )
803 {
804 setColor( dialog.color() );
805 }
806
807 // reactivate button's window
808 activateWindow();
809}
810
811void QgsSymbolButton::setDialogTitle( const QString &title )
812{
813 mDialogTitle = title;
814}
815
817{
818 return mDialogTitle;
819}
820
822{
823 return mSymbol.get();
824}
825
827{
828 mShowNull = showNull;
829}
830
832{
833 return mShowNull;
834}
835
837{
838 mFixedSizeConstraints = fixedSizeConstraints;
839
840 updateSizeHint();
841}
842
844{
845 return mFixedSizeConstraints;
846}
847
849{
850 return !mSymbol;
851}
852
854{
855 setSymbol( nullptr );
856}
857
859{
860 if ( !mDefaultSymbol )
861 {
862 return;
863 }
864
865 setSymbol( mDefaultSymbol->clone() );
866}
@ Point
Points.
Definition qgis.h:359
@ Line
Lines.
Definition qgis.h:360
@ Polygon
Polygons.
Definition qgis.h:361
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 QCursor getThemeCursor(Cursor cursor)
Helper to get a theme cursor.
static QgsColorSchemeRegistry * colorSchemeRegistry()
Returns the application's color scheme registry, used for managing color schemes.
@ Sampler
Color/Value picker.
@ Horizontal
Horizontal ramp.
QList< QgsColorScheme * > schemes() const
Returns all color schemes in the registry.
@ ShowInColorButtonMenu
Show scheme in color button drop-down menu.
void setBaseColor(const QColor &baseColor)
Sets the base color for the color grid.
void colorChanged(const QColor &color)
Emitted when a color has been selected from the widget.
void setColor(const QColor &color, bool emitSignals=false) override
void setDismissOnColorSelection(bool dismiss)
Sets whether the parent menu should be dismissed and closed when a color is selected from the action'...
void colorChanged(const QColor &color)
Emitted when a color has been selected from the widget.
static QPixmap createDragIcon(const QColor &color)
Create an icon for dragging colors.
virtual void setColor(const QColor &color, bool emitSignals=false)
Sets the color for the widget.
@ Alpha
Alpha component (opacity) of color.
@ LayoutVertical
Use a narrower, vertically stacked layout.
void currentColorChanged(const QColor &color)
Emitted when the dialog's color changes.
void setPreviousColor(const QColor &color)
Sets the color to show in an optional "previous color" section.
void setAllowOpacity(bool allowOpacity)
Sets whether opacity modification (transparency) is permitted for the color dialog.
Abstract interface for generating an expression context.
virtual QgsExpressionContext createExpressionContext() const =0
This method needs to be reimplemented in all classes which implement this interface and return an exp...
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
static std::unique_ptr< QgsFillSymbol > createSimple(const QVariantMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties.
static QColor sampleColor(QPoint point)
Samples the color on screen at the specified global point (pixel).
Definition qgsgui.cpp:294
A line symbol type, for rendering LineString and MultiLineString geometries.
void setWidth(double width) const
Sets the width for the whole line symbol.
static std::unique_ptr< QgsLineSymbol > createSimple(const QVariantMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties.
double width() const
Returns the estimated width for the whole symbol, which is the maximum width of all marker symbol lay...
Map canvas is a class for displaying all GIS data types on a canvas.
A marker symbol type, for rendering Point and MultiPoint geometries.
void setSize(double size) const
Sets the size for the whole symbol.
static std::unique_ptr< QgsMarkerSymbol > createSimple(const QVariantMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
double size() const
Returns the estimated size for the whole symbol, which is the maximum size of all marker symbol layer...
A bar for displaying non-blocking messages to the user.
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.
void widgetChanged()
Emitted when the widget state changes.
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.
static void addRecentColor(const QColor &color)
Adds a color to the list of recent colors.
Stores properties relating to a screen.
static QgsStyle * defaultStyle(bool initialize=true)
Returns the default application-wide style.
Definition qgsstyle.cpp:147
void wheelEvent(QWheelEvent *event) override
void setFixedSizeConstraints(bool fixedSizeConstraints)
Sets whether the widget adopts fixed size constraints.
void mouseReleaseEvent(QMouseEvent *e) override
QSize sizeHint() const override
void changeEvent(QEvent *e) override
void setColor(const QColor &color)
Sets the current color for the symbol.
void copySymbol()
Copies the current symbol to the clipboard.
QgsSymbolButton(QWidget *parent=nullptr, const QString &dialogTitle=QString())
Construct a new symbol button.
void copyColor()
Copies the current symbol color to the clipboard.
void setDefaultSymbol(QgsSymbol *symbol)
Sets the default symbol for the button, which is shown in the button's drop-down menu for the "defaul...
void setMessageBar(QgsMessageBar *bar)
Sets the message bar associated with the widget.
~QgsSymbolButton() override
void pasteSymbol()
Pastes a symbol from the clipboard.
void setSymbol(QgsSymbol *symbol)
Sets the symbol for the button.
void mousePressEvent(QMouseEvent *e) override
void dragEnterEvent(QDragEnterEvent *e) override
void showEvent(QShowEvent *e) override
void setSymbolType(Qgis::SymbolType type)
Sets the symbol type which the button requires.
void setDialogTitle(const QString &title)
Sets the title for the symbol settings dialog window.
void keyPressEvent(QKeyEvent *e) override
void setLayer(QgsVectorLayer *layer)
Sets a layer to associate with the widget.
void resizeEvent(QResizeEvent *event) override
void registerExpressionContextGenerator(QgsExpressionContextGenerator *generator)
Register an expression context generator class that will be used to retrieve an expression context fo...
QSize minimumSizeHint() const override
QgsMessageBar * messageBar() const
Returns the message bar associated with the widget.
void setMapCanvas(QgsMapCanvas *canvas)
Sets a map canvas to associate with the widget.
void dropEvent(QDropEvent *e) override
void pasteColor()
Pastes a color from the clipboard to the symbol.
void changed()
Emitted when the symbol's settings are changed.
void setToDefaultSymbol()
Sets symbol to the button's default symbol, if set.
void dragLeaveEvent(QDragLeaveEvent *e) override
bool fixedSizeConstraints() const
Returns true if the widget adopts fixed size constraints.
void setToNull()
Sets symbol to to null.
void setShowNull(bool showNull)
Sets whether a set to null (clear) option is shown in the button's drop-down menu.
QgsVectorLayer * layer() const
Returns the layer associated with the widget.
QgsSymbol * symbol()
Returns the current symbol defined by the button.
const QgsSymbol * defaultSymbol() const
Returns the default symbol for the button, which is shown in the button's drop-down menu for the "def...
QgsMapCanvas * mapCanvas() const
Returns the map canvas associated with the widget.
void mouseMoveEvent(QMouseEvent *e) override
bool isNull() const
Returns true if the current symbol is null.
bool showNull() const
Returns whether the set to null (clear) option is shown in the button's drop-down menu.
static std::unique_ptr< QgsSymbol > symbolFromMimeData(const QMimeData *data)
Attempts to parse mime data as a symbol.
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 QMimeData * symbolToMimeData(const QgsSymbol *symbol)
Creates new mime data from a symbol.
static QColor colorFromMimeData(const QMimeData *data, bool &hasAlpha)
Attempts to parse mime data as a color.
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.
static QMimeData * colorToMimeData(const QColor &color)
Creates mime data from a color.
Symbol selector widget that can be used to select and build a symbol.
void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
QgsSymbol * symbol()
Returns the symbol that is currently active in the widget.
static QgsSymbolSelectorWidget * createWidgetWithSymbolOwnership(std::unique_ptr< QgsSymbol > symbol, QgsStyle *style, QgsVectorLayer *vl, QWidget *parent=nullptr)
Creates a QgsSymbolSelectorWidget which takes ownership of a symbol and maintains the ownership for t...
void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
void setMessageBar(QgsMessageBar *bar)
Sets the message bar associated with the widget.
void setExpressionContext(QgsExpressionContext *context)
Sets the optional expression context used for the widget.
Abstract base class for all rendered symbols.
Definition qgssymbol.h:231
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
static QgsSymbol * defaultSymbol(Qgis::GeometryType geomType)
Returns a new default symbol for the specified geometry type.
Represents a vector layer which manages a vector based dataset.
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,...