QGIS API Documentation 3.99.0-Master (d270888f95f)
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#include <QString>
42
43#include "moc_qgssymbolbutton.cpp"
44
45using namespace Qt::StringLiterals;
46
47QgsSymbolButton::QgsSymbolButton( QWidget *parent, const QString &dialogTitle )
48 : QToolButton( parent )
49 , mDialogTitle( dialogTitle.isEmpty() ? tr( "Symbol Settings" ) : dialogTitle )
50{
51 mSymbol = QgsFillSymbol::createSimple( QVariantMap() );
52
53 setAcceptDrops( true );
54 connect( this, &QAbstractButton::clicked, this, &QgsSymbolButton::showSettingsDialog );
55
56 //setup dropdown menu
57 mMenu = new QMenu( this );
58 connect( mMenu, &QMenu::aboutToShow, this, &QgsSymbolButton::prepareMenu );
59 setMenu( mMenu );
60 setPopupMode( QToolButton::MenuButtonPopup );
61
62 updateSizeHint();
63}
64
65void QgsSymbolButton::updateSizeHint()
66{
67 //make sure height of button looks good under different platforms
68 const QSize size = QToolButton::minimumSizeHint();
69 const int fontHeight = static_cast<int>( Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 1.4 );
70 switch ( mType )
71 {
73 if ( mFixedSizeConstraints )
74 {
75 if ( mSymbol )
76 {
77 mSizeHint = QSize( size.width(), std::max( size.height(), fontHeight * 3 ) );
78 setMaximumWidth( mSizeHint.height() * 1.5 );
79 setMinimumWidth( maximumWidth() );
80 }
81 else
82 {
83 mSizeHint = QSize( size.width(), fontHeight );
84 setMaximumWidth( 999999 );
85 mSizeHint.setWidth( QToolButton::sizeHint().width() );
86 }
87 }
88 else
89 {
90 setMaximumWidth( 999999 );
91 mSizeHint = QSize( size.width(), std::max( size.height(), fontHeight ) );
92 }
93 break;
94
98 mSizeHint = QSize( size.width(), std::max( size.height(), fontHeight ) );
99 break;
100 }
101
102 setMinimumHeight( mSizeHint.height() );
103
104 updateGeometry();
105}
106
108
110{
111 return mSizeHint;
112}
113
115{
116 return mSizeHint;
117}
118
120{
121 if ( type != mType )
122 {
123 switch ( type )
124 {
126 mSymbol = QgsMarkerSymbol::createSimple( QVariantMap() );
127 break;
128
130 mSymbol = QgsLineSymbol::createSimple( QVariantMap() );
131 break;
132
134 mSymbol = QgsFillSymbol::createSimple( QVariantMap() );
135 break;
136
138 break;
139 }
140 }
141 mType = type;
142 updateSizeHint();
143 updatePreview();
144}
145
146void QgsSymbolButton::showSettingsDialog()
147{
148 QgsExpressionContext context;
149 if ( mExpressionContextGenerator )
150 context = mExpressionContextGenerator->createExpressionContext();
151 else
152 {
154 }
155
156 std::unique_ptr<QgsSymbol> newSymbol;
157 if ( mSymbol )
158 {
159 newSymbol.reset( mSymbol->clone() );
160 }
161 else
162 {
163 switch ( mType )
164 {
167 break;
170 break;
173 break;
175 break;
176 }
177 }
178
179 QgsSymbolWidgetContext symbolContext;
180 symbolContext.setExpressionContext( &context );
181 symbolContext.setMapCanvas( mMapCanvas );
182 symbolContext.setMessageBar( mMessageBar );
183
184 QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
185 if ( panel && panel->dockMode() )
186 {
187 QgsSymbolSelectorWidget *widget = QgsSymbolSelectorWidget::createWidgetWithSymbolOwnership( std::move( newSymbol ), QgsStyle::defaultStyle(), mLayer, panel );
188 widget->setPanelTitle( mDialogTitle );
189 widget->setContext( symbolContext );
190 connect( widget, &QgsPanelWidget::widgetChanged, this, [this, widget] { updateSymbolFromWidget( widget ); } );
191 panel->openPanel( widget );
192 }
193 else
194 {
195 QgsSymbolSelectorDialog dialog( newSymbol.get(), QgsStyle::defaultStyle(), mLayer, this );
196 dialog.setWindowTitle( mDialogTitle );
197 dialog.setContext( symbolContext );
198 if ( dialog.exec() )
199 {
200 setSymbol( newSymbol.release() );
201 }
202
203 // reactivate button's window
204 activateWindow();
205 }
206}
207
208void QgsSymbolButton::updateSymbolFromWidget( QgsSymbolSelectorWidget *widget )
209{
210 setSymbol( widget->symbol()->clone() );
211}
212
214{
215 return mMapCanvas;
216}
217
222
224{
225 mMessageBar = bar;
226}
227
229{
230 return mMessageBar;
231}
232
234{
235 return mLayer;
236}
237
239{
240 mLayer = layer;
241}
242
244{
245 mExpressionContextGenerator = generator;
246}
247
249{
250 mDefaultSymbol.reset( symbol );
251}
252
254{
255 return mDefaultSymbol.get();
256}
257
259{
260 mSymbol.reset( symbol );
261 updateSizeHint();
262 updatePreview();
263 emit changed();
264}
265
266void QgsSymbolButton::setColor( const QColor &color )
267{
268 if ( !mSymbol )
269 return;
270
271 QColor opaque = color;
272 opaque.setAlphaF( 1.0 );
273
274 if ( opaque == mSymbol->color() )
275 return;
276
277 mSymbol->setColor( opaque );
278 updatePreview();
279 emit changed();
280}
281
283{
284 QApplication::clipboard()->setMimeData( QgsSymbolLayerUtils::symbolToMimeData( mSymbol.get() ) );
285}
286
288{
289 std::unique_ptr<QgsSymbol> symbol( QgsSymbolLayerUtils::symbolFromMimeData( QApplication::clipboard()->mimeData() ) );
290 if ( symbol && symbol->type() == mType )
291 setSymbol( symbol.release() );
292}
293
295{
296 QApplication::clipboard()->setMimeData( QgsSymbolLayerUtils::colorToMimeData( mSymbol->color() ) );
297}
298
300{
301 QColor clipColor;
302 bool hasAlpha = false;
303 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor, hasAlpha ) )
304 {
305 //paste color
306 setColor( clipColor );
308 }
309}
310
312{
313 if ( mPickingColor )
314 {
315 //don't show dialog if in color picker mode
316 e->accept();
317 return;
318 }
319
320 if ( e->button() == Qt::RightButton )
321 {
322 QToolButton::showMenu();
323 return;
324 }
325 else if ( e->button() == Qt::LeftButton )
326 {
327 mDragStartPosition = e->pos();
328 }
329 QToolButton::mousePressEvent( e );
330}
331
333{
334 if ( mPickingColor )
335 {
336 updatePreview( QgsGui::sampleColor( e->globalPos() ) );
337 e->accept();
338 return;
339 }
340
341 //handle dragging colors/symbols from button
342
343 if ( !( e->buttons() & Qt::LeftButton ) )
344 {
345 //left button not depressed, so not a drag
346 QToolButton::mouseMoveEvent( e );
347 return;
348 }
349
350 if ( ( e->pos() - mDragStartPosition ).manhattanLength() < QApplication::startDragDistance() )
351 {
352 //mouse not moved, so not a drag
353 QToolButton::mouseMoveEvent( e );
354 return;
355 }
356
357 //user is dragging
358 QDrag *drag = new QDrag( this );
359 drag->setMimeData( QgsSymbolLayerUtils::colorToMimeData( mSymbol->color() ) );
360 drag->setPixmap( QgsColorWidget::createDragIcon( mSymbol->color() ) );
361 drag->exec( Qt::CopyAction );
362 setDown( false );
363}
364
366{
367 if ( mPickingColor )
368 {
369 //end color picking operation by sampling the color under cursor
370 stopPicking( e->globalPos() );
371 e->accept();
372 return;
373 }
374
375 QToolButton::mouseReleaseEvent( e );
376}
377
379{
380 if ( !mPickingColor )
381 {
382 //if not picking a color, use default tool button behavior
383 QToolButton::keyPressEvent( e );
384 return;
385 }
386
387 //cancel picking, sampling the color if space was pressed
388 stopPicking( QCursor::pos(), e->key() == Qt::Key_Space );
389}
390
391void QgsSymbolButton::dragEnterEvent( QDragEnterEvent *e )
392{
393 //is dragged data valid color data?
394 QColor mimeColor;
395 bool hasAlpha = false;
396
397 if ( colorFromMimeData( e->mimeData(), mimeColor, hasAlpha ) )
398 {
399 //if so, we accept the drag, and temporarily change the button's color
400 //to match the dragged color. This gives immediate feedback to the user
401 //that colors can be dropped here
402 e->acceptProposedAction();
403 updatePreview( mimeColor );
404 }
405}
406
407void QgsSymbolButton::dragLeaveEvent( QDragLeaveEvent *e )
408{
409 Q_UNUSED( e )
410 //reset button color
411 updatePreview();
412}
413
414void QgsSymbolButton::dropEvent( QDropEvent *e )
415{
416 //is dropped data valid format data?
417 QColor mimeColor;
418 bool hasAlpha = false;
419 if ( colorFromMimeData( e->mimeData(), mimeColor, hasAlpha ) )
420 {
421 //accept drop and set new color
422 e->acceptProposedAction();
423 mimeColor.setAlphaF( 1.0 );
424 mSymbol->setColor( mimeColor );
426 updatePreview();
427 emit changed();
428 }
429 updatePreview();
430}
431
432void QgsSymbolButton::wheelEvent( QWheelEvent *event )
433{
434 if ( isEnabled() && mSymbol )
435 {
436 bool symbolChanged = false;
437 const double increment = ( ( event->modifiers() & Qt::ControlModifier ) ? 0.1 : 1 ) * ( event->angleDelta().y() > 0 ? 1 : -1 );
438 switch ( mSymbol->type() )
439 {
441 {
442 QgsMarkerSymbol *marker = qgis::down_cast<QgsMarkerSymbol *>( mSymbol.get() );
443 if ( marker )
444 {
445 const double size = std::max( 0.0, marker->size() + increment );
446 marker->setSize( size );
447 symbolChanged = true;
448 }
449 break;
450 }
451
453 {
454 QgsLineSymbol *line = qgis::down_cast<QgsLineSymbol *>( mSymbol.get() );
455 if ( line )
456 {
457 const double width = std::max( 0.0, line->width() + increment );
458 line->setWidth( width );
459 symbolChanged = true;
460 }
461 break;
462 }
463
466 break;
467 }
468
469 if ( symbolChanged )
470 {
471 updatePreview();
472 emit changed();
473 }
474
475 event->accept();
476 }
477 else
478 {
479 QToolButton::wheelEvent( event );
480 }
481}
482
483void QgsSymbolButton::prepareMenu()
484{
485 //we need to tear down and rebuild this menu every time it is shown. Otherwise the space allocated to any
486 //QgsColorSwatchGridAction is not recalculated by Qt and the swatch grid may not be the correct size
487 //for the number of colors shown in the grid. Note that we MUST refresh color swatch grids every time this
488 //menu is opened, otherwise color schemes like the recent color scheme grid are meaningless
489 mMenu->clear();
490
491 QAction *configureAction = new QAction( tr( "Configure Symbol…" ), this );
492 mMenu->addAction( configureAction );
493 connect( configureAction, &QAction::triggered, this, &QgsSymbolButton::showSettingsDialog );
494
495 QAction *copySymbolAction = new QAction( tr( "Copy Symbol" ), this );
496 copySymbolAction->setEnabled( !isNull() );
497 mMenu->addAction( copySymbolAction );
498 connect( copySymbolAction, &QAction::triggered, this, &QgsSymbolButton::copySymbol );
499
500 const int iconSize = QgsGuiUtils::scaleIconSize( 16 );
501
502 QAction *pasteSymbolAction = new QAction( tr( "Paste Symbol" ), this );
503 //enable or disable paste action based on current clipboard contents. We always show the paste
504 //action, even if it's disabled, to give hint to the user that pasting symbols is possible
505 std::unique_ptr<QgsSymbol> tempSymbol( QgsSymbolLayerUtils::symbolFromMimeData( QApplication::clipboard()->mimeData() ) );
506 if ( tempSymbol && tempSymbol->type() == mType )
507 {
508 pasteSymbolAction->setIcon( QgsSymbolLayerUtils::symbolPreviewIcon( tempSymbol.get(), QSize( iconSize, iconSize ), 1, nullptr, QgsScreenProperties( screen() ) ) );
509 }
510 else
511 {
512 pasteSymbolAction->setEnabled( false );
513 }
514 mMenu->addAction( pasteSymbolAction );
515 connect( pasteSymbolAction, &QAction::triggered, this, &QgsSymbolButton::pasteSymbol );
516
517 if ( mShowNull )
518 {
519 QAction *nullAction = new QAction( tr( "Clear Current Symbol" ), this );
520 nullAction->setEnabled( !isNull() );
521 mMenu->addAction( nullAction );
522 connect( nullAction, &QAction::triggered, this, &QgsSymbolButton::setToNull );
523 }
524
525 //show default symbol option if set
526 if ( mDefaultSymbol )
527 {
528 QAction *defaultSymbolAction = new QAction( tr( "Default Symbol" ), this );
529 defaultSymbolAction->setIcon( QgsSymbolLayerUtils::symbolPreviewIcon( mDefaultSymbol.get(), QSize( iconSize, iconSize ), 1, nullptr, QgsScreenProperties( screen() ) ) );
530 mMenu->addAction( defaultSymbolAction );
531 connect( defaultSymbolAction, &QAction::triggered, this, &QgsSymbolButton::setToDefaultSymbol );
532 }
533
534 if ( mSymbol )
535 {
536 mMenu->addSeparator();
537
538 QgsColorWheel *colorWheel = new QgsColorWheel( mMenu );
539 colorWheel->setColor( mSymbol->color() );
540 QgsColorWidgetAction *colorAction = new QgsColorWidgetAction( colorWheel, mMenu, mMenu );
541 colorAction->setDismissOnColorSelection( false );
542 connect( colorAction, &QgsColorWidgetAction::colorChanged, this, &QgsSymbolButton::setColor );
543 mMenu->addAction( colorAction );
544
545 QgsColorRampWidget *alphaRamp = new QgsColorRampWidget( mMenu, QgsColorWidget::Alpha, QgsColorRampWidget::Horizontal );
546 QColor alphaColor = mSymbol->color();
547 alphaColor.setAlphaF( mSymbol->opacity() );
548 alphaRamp->setColor( alphaColor );
549 QgsColorWidgetAction *alphaAction = new QgsColorWidgetAction( alphaRamp, mMenu, mMenu );
550 alphaAction->setDismissOnColorSelection( false );
551 connect( alphaAction, &QgsColorWidgetAction::colorChanged, this, [this]( const QColor &color ) {
552 const double opacity = color.alphaF();
553 mSymbol->setOpacity( opacity );
554 updatePreview();
555 emit changed();
556 } );
557 connect( colorAction, &QgsColorWidgetAction::colorChanged, alphaRamp, [alphaRamp]( const QColor &color ) { alphaRamp->setColor( color, false ); } );
558 mMenu->addAction( alphaAction );
559
560 //get schemes with ShowInColorButtonMenu flag set
562 QList<QgsColorScheme *>::iterator it = schemeList.begin();
563 for ( ; it != schemeList.end(); ++it )
564 {
565 QgsColorSwatchGridAction *colorAction = new QgsColorSwatchGridAction( *it, mMenu, u"symbology"_s, this );
566 colorAction->setBaseColor( mSymbol->color() );
567 mMenu->addAction( colorAction );
569 connect( colorAction, &QgsColorSwatchGridAction::colorChanged, this, &QgsSymbolButton::addRecentColor );
570 }
571
572 mMenu->addSeparator();
573
574 QAction *copyColorAction = new QAction( tr( "Copy Color" ), this );
575 mMenu->addAction( copyColorAction );
576 connect( copyColorAction, &QAction::triggered, this, &QgsSymbolButton::copyColor );
577
578 QAction *pasteColorAction = new QAction( tr( "Paste Color" ), this );
579 //enable or disable paste action based on current clipboard contents. We always show the paste
580 //action, even if it's disabled, to give hint to the user that pasting colors is possible
581 QColor clipColor;
582 bool hasAlpha = false;
583 if ( colorFromMimeData( QApplication::clipboard()->mimeData(), clipColor, hasAlpha ) )
584 {
585 pasteColorAction->setIcon( createColorIcon( clipColor ) );
586 }
587 else
588 {
589 pasteColorAction->setEnabled( false );
590 }
591 mMenu->addAction( pasteColorAction );
592 connect( pasteColorAction, &QAction::triggered, this, &QgsSymbolButton::pasteColor );
593
594 QAction *pickColorAction = new QAction( tr( "Pick Color" ), this );
595 mMenu->addAction( pickColorAction );
596 connect( pickColorAction, &QAction::triggered, this, &QgsSymbolButton::activatePicker );
597
598 QAction *chooseColorAction = new QAction( tr( "Choose Color…" ), this );
599 mMenu->addAction( chooseColorAction );
600 connect( chooseColorAction, &QAction::triggered, this, &QgsSymbolButton::showColorDialog );
601 }
602}
603
604void QgsSymbolButton::addRecentColor( const QColor &color )
605{
607}
608
609void QgsSymbolButton::activatePicker()
610{
611 //activate picker color
612 QApplication::setOverrideCursor( QgsApplication::getThemeCursor( QgsApplication::Cursor::Sampler ) );
613 grabMouse();
614 grabKeyboard();
615 mPickingColor = true;
616 setMouseTracking( true );
617}
618
619
621{
622 if ( e->type() == QEvent::EnabledChange )
623 {
624 updatePreview();
625 }
626 QToolButton::changeEvent( e );
627}
628
629void QgsSymbolButton::showEvent( QShowEvent *e )
630{
631 updatePreview();
632 QToolButton::showEvent( e );
633}
634
635void QgsSymbolButton::resizeEvent( QResizeEvent *event )
636{
637 QToolButton::resizeEvent( event );
638 //recalculate icon size and redraw icon
639 mIconSize = QSize();
640 updatePreview();
641}
642
643void QgsSymbolButton::updatePreview( const QColor &color, QgsSymbol *tempSymbol )
644{
645 QSize currentIconSize;
646 //icon size is button size with a small margin
647 if ( menu() )
648 {
649 if ( !mIconSize.isValid() )
650 {
651 //calculate size of push button part of widget (ie, without the menu dropdown button part)
652 QStyleOptionToolButton opt;
653 initStyleOption( &opt );
654 const QRect buttonSize = QApplication::style()->subControlRect( QStyle::CC_ToolButton, &opt, QStyle::SC_ToolButton, this );
655 //make sure height of icon looks good under different platforms
656#ifdef Q_OS_WIN
657 mIconSize = QSize( buttonSize.width() - 10, height() - 6 );
658#else
659 mIconSize = QSize( buttonSize.width() - 10, height() - 12 );
660#endif
661 }
662 currentIconSize = mIconSize;
663 }
664 else
665 {
666 //no menu
667#ifdef Q_OS_WIN
668 currentIconSize = QSize( width() - 10, height() - 6 );
669#else
670 currentIconSize = QSize( width() - 10, height() - 12 );
671#endif
672 }
673
674 if ( !currentIconSize.isValid() || currentIconSize.width() <= 0 || currentIconSize.height() <= 0 )
675 {
676 return;
677 }
678
679 std::unique_ptr<QgsSymbol> previewSymbol;
680
681 if ( tempSymbol )
682 {
683 previewSymbol.reset( tempSymbol->clone() );
684 }
685 else if ( mSymbol )
686 {
687 previewSymbol.reset( mSymbol->clone() );
688 }
689 else
690 {
691 setIconSize( currentIconSize );
692 setIcon( QIcon() );
693 setToolTip( QString() );
694 return;
695 }
696
697 if ( color.isValid() )
698 previewSymbol->setColor( color );
699
700 //create an icon pixmap
701 const QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( previewSymbol.get(), currentIconSize, 0, nullptr, QgsScreenProperties( screen() ) );
702 setIconSize( currentIconSize );
703 setIcon( icon );
704
705 // set tooltip
706 // create very large preview image
707 const int width = static_cast<int>( Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 23 );
708 const int height = static_cast<int>( width / 1.61803398875 ); // golden ratio
709
710 const QPixmap pm = QgsSymbolLayerUtils::symbolPreviewPixmap( previewSymbol.get(), QSize( width, height ), height / 20, nullptr, false, nullptr, nullptr, QgsScreenProperties( screen() ) );
711 QByteArray data;
712 QBuffer buffer( &data );
713 pm.save( &buffer, "PNG", 100 );
714 setToolTip( u"<img src='data:image/png;base64, %3' width=\"%4\">"_s.arg( QString( data.toBase64() ) ).arg( width ) );
715}
716
717bool QgsSymbolButton::colorFromMimeData( const QMimeData *mimeData, QColor &resultColor, bool &hasAlpha )
718{
719 hasAlpha = false;
720 const QColor mimeColor = QgsSymbolLayerUtils::colorFromMimeData( mimeData, hasAlpha );
721
722 if ( mimeColor.isValid() )
723 {
724 resultColor = mimeColor;
725 return true;
726 }
727
728 //could not get color from mime data
729 return false;
730}
731
732QPixmap QgsSymbolButton::createColorIcon( const QColor &color ) const
733{
734 //create an icon pixmap
735 const int iconSize = QgsGuiUtils::scaleIconSize( 16 );
736 QPixmap pixmap( iconSize, iconSize );
737 pixmap.fill( Qt::transparent );
738
739 QPainter p;
740 p.begin( &pixmap );
741
742 //draw color over pattern
743 p.setBrush( QBrush( color ) );
744
745 //draw border
746 p.setPen( QColor( 197, 197, 197 ) );
747 p.drawRect( 0, 0, iconSize - 1, iconSize - 1 );
748 p.end();
749 return pixmap;
750}
751
752void QgsSymbolButton::stopPicking( QPoint eventPos, bool samplingColor )
753{
754 //release mouse and keyboard, and reset cursor
755 releaseMouse();
756 releaseKeyboard();
757 QgsApplication::restoreOverrideCursor();
758 setMouseTracking( false );
759 mPickingColor = false;
760
761 if ( !samplingColor )
762 {
763 //not sampling color, restore old icon
764 updatePreview();
765 return;
766 }
767
768 const QColor newColor = QgsGui::sampleColor( eventPos );
769 setColor( newColor );
770 addRecentColor( newColor );
771}
772
773void QgsSymbolButton::showColorDialog()
774{
775 if ( !mSymbol )
776 return;
777
778 QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
779 if ( panel && panel->dockMode() )
780 {
781 const QColor currentColor = mSymbol->color();
782 QgsCompoundColorWidget *colorWidget = new QgsCompoundColorWidget( panel, currentColor, QgsCompoundColorWidget::LayoutVertical );
783 colorWidget->setPanelTitle( tr( "Symbol Color" ) );
784 colorWidget->setAllowOpacity( true );
785
786 if ( currentColor.isValid() )
787 {
788 colorWidget->setPreviousColor( currentColor );
789 }
790
791 connect( colorWidget, &QgsCompoundColorWidget::currentColorChanged, this, [this]( const QColor &newColor ) {
792 if ( newColor.isValid() )
793 {
794 setColor( newColor );
795 }
796 } );
797 panel->openPanel( colorWidget );
798 return;
799 }
800
801 QgsColorDialog dialog( this, Qt::WindowFlags(), mSymbol->color() );
802 dialog.setTitle( tr( "Symbol Color" ) );
803 dialog.setAllowOpacity( true );
804
805 if ( dialog.exec() && dialog.color().isValid() )
806 {
807 setColor( dialog.color() );
808 }
809
810 // reactivate button's window
811 activateWindow();
812}
813
814void QgsSymbolButton::setDialogTitle( const QString &title )
815{
816 mDialogTitle = title;
817}
818
820{
821 return mDialogTitle;
822}
823
825{
826 return mSymbol.get();
827}
828
830{
831 mShowNull = showNull;
832}
833
835{
836 return mShowNull;
837}
838
840{
841 mFixedSizeConstraints = fixedSizeConstraints;
842
843 updateSizeHint();
844}
845
847{
848 return mFixedSizeConstraints;
849}
850
852{
853 return !mSymbol;
854}
855
857{
858 setSymbol( nullptr );
859}
860
862{
863 if ( !mDefaultSymbol )
864 {
865 return;
866 }
867
868 setSymbol( mDefaultSymbol->clone() );
869}
@ Point
Points.
Definition qgis.h:366
@ Line
Lines.
Definition qgis.h:367
@ Polygon
Polygons.
Definition qgis.h:368
SymbolType
Symbol types.
Definition qgis.h:629
@ Marker
Marker symbol.
Definition qgis.h:630
@ Line
Line symbol.
Definition qgis.h:631
@ Fill
Fill symbol.
Definition qgis.h:632
@ Hybrid
Hybrid symbol.
Definition qgis.h:633
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition qgis.h:6499
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:297
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:150
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,...