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