QGIS API Documentation 3.99.0-Master (d270888f95f)
Loading...
Searching...
No Matches
qgscolorschemelist.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgscolorschemelist.cpp
3 ----------------------
4 Date : August 2014
5 Copyright : (C) 2014 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 "qgscolorschemelist.h"
17
18#include "qgsapplication.h"
19#include "qgscolordialog.h"
20#include "qgslogger.h"
21#include "qgssettings.h"
22#include "qgssymbollayerutils.h"
23
24#include <QClipboard>
25#include <QColorDialog>
26#include <QFileDialog>
27#include <QKeyEvent>
28#include <QMessageBox>
29#include <QMimeData>
30#include <QPainter>
31#include <QString>
32
33#include "moc_qgscolorschemelist.cpp"
34
35using namespace Qt::StringLiterals;
36
37#ifdef ENABLE_MODELTEST
38#include "modeltest.h"
39#endif
40
41QgsColorSchemeList::QgsColorSchemeList( QWidget *parent, QgsColorScheme *scheme, const QString &context, const QColor &baseColor )
42 : QTreeView( parent )
43 , mScheme( scheme )
44{
45 mModel = new QgsColorSchemeModel( scheme, context, baseColor, this );
46#ifdef ENABLE_MODELTEST
47 new ModelTest( mModel, this );
48#endif
49 setModel( mModel );
50
51 mSwatchDelegate = new QgsColorSwatchDelegate( this );
52 setItemDelegateForColumn( 0, mSwatchDelegate );
53
54 setRootIsDecorated( false );
55 setSelectionMode( QAbstractItemView::ExtendedSelection );
56 setSelectionBehavior( QAbstractItemView::SelectRows );
57 setDragEnabled( true );
58 setAcceptDrops( true );
59 setDragDropMode( QTreeView::DragDrop );
60 setDropIndicatorShown( true );
61 setDefaultDropAction( Qt::CopyAction );
62}
63
64void QgsColorSchemeList::setScheme( QgsColorScheme *scheme, const QString &context, const QColor &baseColor )
65{
66 mScheme = scheme;
67 mModel->setScheme( scheme, context, baseColor );
68}
69
71{
72 if ( !mScheme || !mScheme->isEditable() )
73 {
74 return false;
75 }
76
77 mScheme->setColors( mModel->colors(), mModel->context(), mModel->baseColor() );
78 return true;
79}
80
82{
83 QList<int> rows;
84 const auto constSelectedIndexes = selectedIndexes();
85 for ( const QModelIndex &index : constSelectedIndexes )
86 {
87 rows << index.row();
88 }
89 //remove duplicates
90 QList<int> rowsToRemove = qgis::setToList( qgis::listToSet( rows ) );
91
92 //remove rows in descending order
93 std::sort( rowsToRemove.begin(), rowsToRemove.end(), std::greater<int>() );
94 const auto constRowsToRemove = rowsToRemove;
95 for ( const int row : constRowsToRemove )
96 {
97 mModel->removeRow( row );
98 }
99}
100
101void QgsColorSchemeList::addColor( const QColor &color, const QString &label, bool allowDuplicate )
102{
103 mModel->addColor( color, label, allowDuplicate );
104}
105
107{
108 const QgsNamedColorList pastedColors = QgsSymbolLayerUtils::colorListFromMimeData( QApplication::clipboard()->mimeData() );
109
110 if ( pastedColors.length() == 0 )
111 {
112 //no pasted colors
113 return;
114 }
115
116 //insert pasted colors
117 QgsNamedColorList::const_iterator colorIt = pastedColors.constBegin();
118 for ( ; colorIt != pastedColors.constEnd(); ++colorIt )
119 {
120 mModel->addColor( ( *colorIt ).first, !( *colorIt ).second.isEmpty() ? ( *colorIt ).second : QgsSymbolLayerUtils::colorToName( ( *colorIt ).first ) );
121 }
122}
123
125{
126 QList<int> rows;
127 const auto constSelectedIndexes = selectedIndexes();
128 for ( const QModelIndex &index : constSelectedIndexes )
129 {
130 rows << index.row();
131 }
132 //remove duplicates
133 const QList<int> rowsToCopy = qgis::setToList( qgis::listToSet( rows ) );
134
135 QgsNamedColorList colorsToCopy;
136 const auto constRowsToCopy = rowsToCopy;
137 for ( const int row : constRowsToCopy )
138 {
139 colorsToCopy << mModel->colors().at( row );
140 }
141
142 //copy colors
143 QMimeData *mimeData = QgsSymbolLayerUtils::colorListToMimeData( colorsToCopy );
144 QApplication::clipboard()->setMimeData( mimeData );
145}
146
148{
149 QgsSettings s;
150 const QString lastDir = s.value( u"/UI/lastGplPaletteDir"_s, QDir::homePath() ).toString();
151 const QString filePath = QFileDialog::getOpenFileName( this, tr( "Select Palette File" ), lastDir, u"GPL (*.gpl);;All files (*.*)"_s );
152 activateWindow();
153 if ( filePath.isEmpty() )
154 {
155 return;
156 }
157
158 //check if file exists
159 const QFileInfo fileInfo( filePath );
160 if ( !fileInfo.exists() || !fileInfo.isReadable() )
161 {
162 QMessageBox::critical( nullptr, tr( "Import Colors" ), tr( "Error, file does not exist or is not readable." ) );
163 return;
164 }
165
166 s.setValue( u"/UI/lastGplPaletteDir"_s, fileInfo.absolutePath() );
167 QFile file( filePath );
168 const bool importOk = importColorsFromGpl( file );
169 if ( !importOk )
170 {
171 QMessageBox::critical( nullptr, tr( "Import Colors" ), tr( "Error, no colors found in palette file." ) );
172 return;
173 }
174}
175
177{
178 QgsSettings s;
179 const QString lastDir = s.value( u"/UI/lastGplPaletteDir"_s, QDir::homePath() ).toString();
180 QString fileName = QFileDialog::getSaveFileName( this, tr( "Palette file" ), lastDir, u"GPL (*.gpl)"_s );
181 activateWindow();
182 if ( fileName.isEmpty() )
183 {
184 return;
185 }
186
187 // ensure filename contains extension
188 if ( !fileName.endsWith( ".gpl"_L1, Qt::CaseInsensitive ) )
189 {
190 fileName += ".gpl"_L1;
191 }
192
193 const QFileInfo fileInfo( fileName );
194 s.setValue( u"/UI/lastGplPaletteDir"_s, fileInfo.absolutePath() );
195
196 QFile file( fileName );
197 const bool exportOk = exportColorsToGpl( file );
198 if ( !exportOk )
199 {
200 QMessageBox::critical( nullptr, tr( "Export Colors" ), tr( "Error writing palette file." ) );
201 return;
202 }
203}
204
205void QgsColorSchemeList::keyPressEvent( QKeyEvent *event )
206{
207 //listen out for delete/backspace presses and remove selected colors
208 if ( ( event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete ) )
209 {
210 QList<int> rows;
211 const auto constSelectedIndexes = selectedIndexes();
212 for ( const QModelIndex &index : constSelectedIndexes )
213 {
214 rows << index.row();
215 }
216 //remove duplicates
217 QList<int> rowsToRemove = qgis::setToList( qgis::listToSet( rows ) );
218
219 //remove rows in descending order
220 std::sort( rowsToRemove.begin(), rowsToRemove.end(), std::greater<int>() );
221 const auto constRowsToRemove = rowsToRemove;
222 for ( const int row : constRowsToRemove )
223 {
224 mModel->removeRow( row );
225 }
226 return;
227 }
228
229 QTreeView::keyPressEvent( event );
230}
231
232void QgsColorSchemeList::mousePressEvent( QMouseEvent *event )
233{
234 if ( event->button() == Qt::LeftButton )
235 {
236 //record press start position
237 mDragStartPosition = event->pos();
238 }
239 QTreeView::mousePressEvent( event );
240}
241
243{
244 if ( ( event->button() == Qt::LeftButton ) && ( event->pos() - mDragStartPosition ).manhattanLength() <= QApplication::startDragDistance() )
245 {
246 //just a click, not a drag
247
248 //if only one item is selected, emit color changed signal
249 //(if multiple are selected, user probably was interacting with color list rather than trying to pick a color)
250 if ( selectedIndexes().length() == mModel->columnCount() )
251 {
252 const QModelIndex selectedColor = selectedIndexes().at( 0 );
253 emit colorSelected( mModel->colors().at( selectedColor.row() ).first );
254 }
255 }
256
257 QTreeView::mouseReleaseEvent( event );
258}
259
261{
262 QgsNamedColorList importedColors;
263 bool ok = false;
264 QString name;
265 importedColors = QgsSymbolLayerUtils::importColorsFromGpl( file, ok, name );
266 if ( !ok )
267 {
268 return false;
269 }
270
271 if ( importedColors.length() == 0 )
272 {
273 //no imported colors
274 return false;
275 }
276
277 //insert imported colors
278 QgsNamedColorList::const_iterator colorIt = importedColors.constBegin();
279 for ( ; colorIt != importedColors.constEnd(); ++colorIt )
280 {
281 mModel->addColor( ( *colorIt ).first, !( *colorIt ).second.isEmpty() ? ( *colorIt ).second : QgsSymbolLayerUtils::colorToName( ( *colorIt ).first ) );
282 }
283
284 return true;
285}
286
288{
289 return QgsSymbolLayerUtils::saveColorsToGpl( file, QString(), mModel->colors() );
290}
291
293{
294 if ( !mModel )
295 {
296 return false;
297 }
298
299 return mModel->isDirty();
300}
301
303{
304 return mScheme;
305}
306
307//
308// QgsColorSchemeModel
309//
310
311QgsColorSchemeModel::QgsColorSchemeModel( QgsColorScheme *scheme, const QString &context, const QColor &baseColor, QObject *parent )
312 : QAbstractItemModel( parent )
313 , mScheme( scheme )
314 , mContext( context )
315 , mBaseColor( baseColor )
316{
317 if ( scheme )
318 {
319 mColors = scheme->fetchColors( context, baseColor );
320 }
321}
322
323QModelIndex QgsColorSchemeModel::index( int row, int column, const QModelIndex &parent ) const
324{
325 if ( column < 0 || column >= columnCount() )
326 {
327 //column out of bounds
328 return QModelIndex();
329 }
330
331 if ( !parent.isValid() && row >= 0 && row < mColors.size() )
332 {
333 //return an index for the color item at this position
334 return createIndex( row, column );
335 }
336
337 //only top level supported
338 return QModelIndex();
339}
340
341QModelIndex QgsColorSchemeModel::parent( const QModelIndex &index ) const
342{
343 Q_UNUSED( index )
344
345 //all items are top level
346 return QModelIndex();
347}
348
349int QgsColorSchemeModel::rowCount( const QModelIndex &parent ) const
350{
351 if ( !parent.isValid() )
352 {
353 return mColors.size();
354 }
355 else
356 {
357 //no children
358 return 0;
359 }
360}
361
362int QgsColorSchemeModel::columnCount( const QModelIndex &parent ) const
363{
364 Q_UNUSED( parent )
365 return 2;
366}
367
368QVariant QgsColorSchemeModel::data( const QModelIndex &index, int role ) const
369{
370 if ( !index.isValid() )
371 return QVariant();
372
373 const QPair<QColor, QString> namedColor = mColors.at( index.row() );
374 switch ( role )
375 {
376 case Qt::DisplayRole:
377 case Qt::EditRole:
378 switch ( index.column() )
379 {
380 case ColorSwatch:
381 return namedColor.first;
382 case ColorLabel:
383 return namedColor.second;
384 default:
385 return QVariant();
386 }
387
388 case Qt::TextAlignmentRole:
389 return static_cast<Qt::Alignment::Int>( Qt::AlignLeft | Qt::AlignVCenter );
390
391 default:
392 return QVariant();
393 }
394}
395
396Qt::ItemFlags QgsColorSchemeModel::flags( const QModelIndex &index ) const
397{
398 Qt::ItemFlags flags = QAbstractItemModel::flags( index );
399
400 if ( !index.isValid() )
401 {
402 return flags | Qt::ItemIsDropEnabled;
403 }
404
405 switch ( index.column() )
406 {
407 case ColorSwatch:
408 case ColorLabel:
409 if ( mScheme && mScheme->isEditable() )
410 {
411 flags = flags | Qt::ItemIsEditable;
412 }
413 return flags | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
414 default:
415 return flags | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
416 }
417}
418
419bool QgsColorSchemeModel::setData( const QModelIndex &index, const QVariant &value, int role )
420{
421 Q_UNUSED( role )
422
423 if ( !mScheme || !mScheme->isEditable() )
424 return false;
425
426 if ( !index.isValid() )
427 return false;
428
429 if ( index.row() >= mColors.length() )
430 return false;
431
432 switch ( index.column() )
433 {
434 case ColorSwatch:
435 mColors[index.row()].first = value.value<QColor>();
436 emit dataChanged( index, index );
437 mIsDirty = true;
438 return true;
439
440 case ColorLabel:
441 mColors[index.row()].second = value.toString();
442 emit dataChanged( index, index );
443 mIsDirty = true;
444 return true;
445
446 default:
447 return false;
448 }
449}
450
451QVariant QgsColorSchemeModel::headerData( int section, Qt::Orientation orientation, int role ) const
452{
453 switch ( role )
454 {
455 case Qt::DisplayRole:
456 {
457 switch ( section )
458 {
459 case ColorSwatch:
460 return tr( "Color" );
461 case ColorLabel:
462 return tr( "Label" );
463 default:
464 return QVariant();
465 }
466 }
467
468 case Qt::TextAlignmentRole:
469 switch ( section )
470 {
471 case ColorSwatch:
472 return static_cast<Qt::Alignment::Int>( Qt::AlignHCenter | Qt::AlignVCenter );
473 case ColorLabel:
474 return static_cast<Qt::Alignment::Int>( Qt::AlignLeft | Qt::AlignVCenter );
475 default:
476 return QVariant();
477 }
478 default:
479 return QAbstractItemModel::headerData( section, orientation, role );
480 }
481}
482
484{
485 if ( mScheme && mScheme->isEditable() )
486 {
487 return Qt::CopyAction | Qt::MoveAction;
488 }
489 else
490 {
491 return Qt::CopyAction;
492 }
493}
494
496{
497 if ( !mScheme || !mScheme->isEditable() )
498 {
499 return QStringList();
500 }
501
502 QStringList types;
503 types << u"text/xml"_s;
504 types << u"text/plain"_s;
505 types << u"application/x-color"_s;
506 types << u"application/x-colorobject-list"_s;
507 return types;
508}
509
510QMimeData *QgsColorSchemeModel::mimeData( const QModelIndexList &indexes ) const
511{
512 QgsNamedColorList colorList;
513
514 QModelIndexList::const_iterator indexIt = indexes.constBegin();
515 for ( ; indexIt != indexes.constEnd(); ++indexIt )
516 {
517 if ( ( *indexIt ).column() > 0 )
518 continue;
519
520 colorList << qMakePair( mColors[( *indexIt ).row()].first, mColors[( *indexIt ).row()].second );
521 }
522
523 QMimeData *mimeData = QgsSymbolLayerUtils::colorListToMimeData( colorList );
524 return mimeData;
525}
526
527bool QgsColorSchemeModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent )
528{
529 Q_UNUSED( column )
530
531 if ( !mScheme || !mScheme->isEditable() )
532 {
533 return false;
534 }
535
536 if ( action == Qt::IgnoreAction )
537 {
538 return true;
539 }
540
541 if ( parent.isValid() )
542 {
543 return false;
544 }
545
546 int beginRow = row != -1 ? row : rowCount( QModelIndex() );
548
549 if ( droppedColors.length() == 0 )
550 {
551 //no dropped colors
552 return false;
553 }
554
555 //any existing colors? if so, remove them first
556 QgsNamedColorList::const_iterator colorIt = droppedColors.constBegin();
557 for ( ; colorIt != droppedColors.constEnd(); ++colorIt )
558 {
559 //dest color
560 const QPair<QColor, QString> color = qMakePair( ( *colorIt ).first, !( *colorIt ).second.isEmpty() ? ( *colorIt ).second : QgsSymbolLayerUtils::colorToName( ( *colorIt ).first ) );
561 //if color already exists, remove it
562 const int existingIndex = mColors.indexOf( color );
563 if ( existingIndex >= 0 )
564 {
565 if ( existingIndex < beginRow )
566 {
567 //color is before destination row, so decrease destination row to account for removal
568 beginRow--;
569 }
570
571 beginRemoveRows( parent, existingIndex, existingIndex );
572 mColors.removeAt( existingIndex );
573 endRemoveRows();
574 }
575 }
576
577 //insert dropped colors
578 insertRows( beginRow, droppedColors.length(), QModelIndex() );
579 colorIt = droppedColors.constBegin();
580 for ( ; colorIt != droppedColors.constEnd(); ++colorIt )
581 {
582 const QModelIndex colorIdx = index( beginRow, 0, QModelIndex() );
583 setData( colorIdx, QVariant( ( *colorIt ).first ) );
584 const QModelIndex labelIdx = index( beginRow, 1, QModelIndex() );
585 setData( labelIdx, !( *colorIt ).second.isEmpty() ? ( *colorIt ).second : QgsSymbolLayerUtils::colorToName( ( *colorIt ).first ) );
586 beginRow++;
587 }
588 mIsDirty = true;
589
590 return true;
591}
592
593void QgsColorSchemeModel::setScheme( QgsColorScheme *scheme, const QString &context, const QColor &baseColor )
594{
595 mScheme = scheme;
596 mContext = context;
597 mBaseColor = baseColor;
598 mIsDirty = false;
599 beginResetModel();
600 mColors = scheme->fetchColors( mContext, mBaseColor );
601 endResetModel();
602}
603
604bool QgsColorSchemeModel::removeRows( int row, int count, const QModelIndex &parent )
605{
606 if ( !mScheme || !mScheme->isEditable() )
607 {
608 return false;
609 }
610
611 if ( parent.isValid() )
612 {
613 return false;
614 }
615
616 if ( row >= mColors.count() )
617 {
618 return false;
619 }
620
621 for ( int i = row + count - 1; i >= row; --i )
622 {
623 beginRemoveRows( parent, i, i );
624 mColors.removeAt( i );
625 endRemoveRows();
626 }
627
628 mIsDirty = true;
629 return true;
630}
631
632bool QgsColorSchemeModel::insertRows( int row, int count, const QModelIndex &parent )
633{
634 Q_UNUSED( parent )
635
636 if ( !mScheme || !mScheme->isEditable() )
637 {
638 return false;
639 }
640
641 beginInsertRows( QModelIndex(), row, row + count - 1 );
642 for ( int i = row; i < row + count; ++i )
643 {
644 const QPair<QColor, QString> newColor;
645 mColors.insert( i, newColor );
646 }
647 endInsertRows();
648 mIsDirty = true;
649 return true;
650}
651
652void QgsColorSchemeModel::addColor( const QColor &color, const QString &label, bool allowDuplicate )
653{
654 if ( !mScheme || !mScheme->isEditable() )
655 {
656 return;
657 }
658
659 if ( !allowDuplicate )
660 {
661 //matches existing color? if so, remove it first
662 const QPair<QColor, QString> newColor = qMakePair( color, !label.isEmpty() ? label : QgsSymbolLayerUtils::colorToName( color ) );
663 //if color already exists, remove it
664 const int existingIndex = mColors.indexOf( newColor );
665 if ( existingIndex >= 0 )
666 {
667 beginRemoveRows( QModelIndex(), existingIndex, existingIndex );
668 mColors.removeAt( existingIndex );
669 endRemoveRows();
670 }
671 }
672
673 const int row = rowCount();
674 insertRow( row );
675 const QModelIndex colorIdx = index( row, 0, QModelIndex() );
676 setData( colorIdx, QVariant( color ) );
677 const QModelIndex labelIdx = index( row, 1, QModelIndex() );
678 setData( labelIdx, QVariant( label ) );
679 mIsDirty = true;
680}
681
682
683//
684// QgsColorSwatchDelegate
685//
687 : QAbstractItemDelegate( parent )
688 , mParent( parent )
689{
690}
691
692void QgsColorSwatchDelegate::paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const
693{
694 if ( option.state & QStyle::State_Selected )
695 {
696 painter->setPen( QPen( Qt::NoPen ) );
697 if ( option.state & QStyle::State_Active )
698 {
699 painter->setBrush( QBrush( option.widget->palette().highlight() ) );
700 }
701 else
702 {
703 painter->setBrush( QBrush( option.widget->palette().color( QPalette::Inactive, QPalette::Highlight ) ) );
704 }
705 painter->drawRect( option.rect );
706 }
707
708 QColor color = index.model()->data( index, Qt::DisplayRole ).value<QColor>();
709 if ( !color.isValid() )
710 {
711 return;
712 }
713
714 QRect rect = option.rect;
715 const int iconSize = Qgis::UI_SCALE_FACTOR * option.fontMetrics.horizontalAdvance( 'X' ) * 4;
716
717 const int cornerSize = iconSize / 6;
718 //center it
719 rect.setLeft( option.rect.center().x() - iconSize / 2 );
720
721 rect.setSize( QSize( iconSize, iconSize ) );
722 rect.adjust( 0, 1, 0, 1 );
723 //create an icon pixmap
724 const QgsScopedQPainterState painterState( painter );
725 painter->setRenderHint( QPainter::Antialiasing );
726 painter->setPen( Qt::NoPen );
727 if ( color.alpha() < 255 )
728 {
729 //start with checkboard pattern
730 const QBrush checkBrush = QBrush( transparentBackground() );
731 painter->setBrush( checkBrush );
732 painter->drawRoundedRect( rect, cornerSize, cornerSize );
733 //draw semi-transparent color on top
734 painter->setBrush( color );
735 painter->drawRoundedRect( rect, cornerSize, cornerSize );
736 //draw fully opaque color on the left side
737 const QRectF clipRect( rect.left(), rect.top(), static_cast<qreal>( rect.width() ) / 2.0, rect.height() );
738 painter->setClipRect( clipRect );
739 color.setAlpha( 255 );
740 painter->setBrush( color );
741 painter->drawRoundedRect( rect, cornerSize, cornerSize );
742 }
743 else
744 {
745 painter->setBrush( color );
746 painter->drawRoundedRect( rect, cornerSize, cornerSize );
747 }
748}
749
750QPixmap QgsColorSwatchDelegate::transparentBackground() const
751{
752 static QPixmap sTranspBkgrd;
753
754 if ( sTranspBkgrd.isNull() )
755 sTranspBkgrd = QgsApplication::getThemePixmap( u"/transp-background_8x8.png"_s );
756
757 return sTranspBkgrd;
758}
759
760QSize QgsColorSwatchDelegate::sizeHint( const QStyleOptionViewItem &option, const QModelIndex &index ) const
761{
762 Q_UNUSED( index )
763
764 const int iconSize = Qgis::UI_SCALE_FACTOR * option.fontMetrics.horizontalAdvance( 'X' ) * 4;
765 return QSize( iconSize, iconSize * 32 / 30.0 );
766}
767
768bool QgsColorSwatchDelegate::editorEvent( QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index )
769{
770 Q_UNUSED( option )
771 if ( event->type() == QEvent::MouseButtonDblClick )
772 {
773 if ( !index.model()->flags( index ).testFlag( Qt::ItemIsEditable ) )
774 {
775 //item not editable
776 return false;
777 }
778
779 const QColor color = index.model()->data( index, Qt::DisplayRole ).value<QColor>();
780
781 QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( qobject_cast<QWidget *>( parent() ) );
782 if ( panel && panel->dockMode() )
783 {
785 colorWidget->setPanelTitle( tr( "Select Color" ) );
786 colorWidget->setAllowOpacity( true );
787 colorWidget->setProperty( "index", index );
788 connect( colorWidget, &QgsCompoundColorWidget::currentColorChanged, this, &QgsColorSwatchDelegate::colorChanged );
789 panel->openPanel( colorWidget );
790 return true;
791 }
792
793 const QColor newColor = QgsColorDialog::getColor( color, mParent, tr( "Select color" ), true );
794 if ( !newColor.isValid() )
795 {
796 return false;
797 }
798
799 return model->setData( index, newColor, Qt::EditRole );
800 }
801
802 return false;
803}
804
805void QgsColorSwatchDelegate::colorChanged()
806{
807 if ( QgsCompoundColorWidget *colorWidget = qobject_cast<QgsCompoundColorWidget *>( sender() ) )
808 {
809 const QModelIndex index = colorWidget->property( "index" ).toModelIndex();
810 const_cast<QAbstractItemModel *>( index.model() )->setData( index, colorWidget->color(), Qt::EditRole );
811 }
812}
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition qgis.h:6499
static QPixmap getThemePixmap(const QString &name, const QColor &foreColor=QColor(), const QColor &backColor=QColor(), int size=16)
Helper to get a theme icon as a pixmap.
static QColor getColor(const QColor &initialColor, QWidget *parent, const QString &title=QString(), bool allowOpacity=false)
Returns a color selection from a color dialog.
bool exportColorsToGpl(QFile &file)
Export colors to a GPL palette file from the list.
void setScheme(QgsColorScheme *scheme, const QString &context=QString(), const QColor &baseColor=QColor())
Sets the color scheme to show in the list.
void pasteColors()
Pastes colors from clipboard to the list.
void removeSelection()
Removes any selected colors from the list.
bool importColorsFromGpl(QFile &file)
Import colors from a GPL palette file to the list.
void copyColors()
Copies colors from the list to the clipboard.
bool isDirty() const
Returns whether the color scheme list has been modified.
void mouseReleaseEvent(QMouseEvent *event) override
void mousePressEvent(QMouseEvent *event) override
QgsColorScheme * scheme()
Returns the scheme currently selected in the list.
void addColor(const QColor &color, const QString &label=QString(), bool allowDuplicate=false)
Adds a color to the list.
void showExportColorsDialog()
Displays a file picker dialog allowing users to export colors from the list into a file.
void colorSelected(const QColor &color)
Emitted when a color is selected from the list.
void keyPressEvent(QKeyEvent *event) override
QgsColorSchemeList(QWidget *parent=nullptr, QgsColorScheme *scheme=nullptr, const QString &context=QString(), const QColor &baseColor=QColor())
Construct a new color swatch grid.
bool saveColorsToScheme()
Saves the current colors shown in the list back to a color scheme, if supported by the color scheme.
void showImportColorsDialog()
Displays a file picker dialog allowing users to import colors into the list from a file.
A model for colors in a color scheme.
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
void addColor(const QColor &color, const QString &label=QString(), bool allowDuplicate=false)
Add a color to the list.
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
QColor baseColor() const
Gets the base color for the color scheme used by the model.
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Qt::DropActions supportedDropActions() const override
QModelIndex parent(const QModelIndex &index) const override
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
Qt::ItemFlags flags(const QModelIndex &index) const override
void setScheme(QgsColorScheme *scheme, const QString &context=QString(), const QColor &baseColor=QColor())
Sets the color scheme to show in the widget.
bool insertRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
QMimeData * mimeData(const QModelIndexList &indexes) const override
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
QgsColorSchemeModel(QgsColorScheme *scheme, const QString &context=QString(), const QColor &baseColor=QColor(), QObject *parent=nullptr)
Constructor.
QStringList mimeTypes() const override
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override
QString context() const
Gets the current color scheme context for the model.
int columnCount(const QModelIndex &parent=QModelIndex()) const override
Abstract base class for color schemes.
virtual QgsNamedColorList fetchColors(const QString &context=QString(), const QColor &baseColor=QColor())=0
Gets a list of colors from the scheme.
A delegate for showing a color swatch in a list.
QgsColorSwatchDelegate(QWidget *parent=nullptr)
bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
A custom QGIS widget for selecting a color, including options for selecting colors via hue wheel,...
@ LayoutVertical
Use a narrower, vertically stacked layout.
void currentColorChanged(const QColor &color)
Emitted when the dialog's color changes.
void setAllowOpacity(bool allowOpacity)
Sets whether opacity modification (transparency) is permitted for the color dialog.
Base class for any widget that can be shown as an inline panel.
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.
Scoped object for saving and restoring a QPainter object's state.
Stores settings for use within QGIS.
Definition qgssettings.h:68
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
static bool saveColorsToGpl(QFile &file, const QString &paletteName, const QgsNamedColorList &colors)
Exports colors to a gpl GIMP palette file.
static QgsNamedColorList colorListFromMimeData(const QMimeData *data)
Attempts to parse mime data as a list of named colors.
static QMimeData * colorListToMimeData(const QgsNamedColorList &colorList, bool allFormats=true)
Creates mime data from a list of named colors.
static QgsNamedColorList importColorsFromGpl(QFile &file, bool &ok, QString &name)
Imports colors from a gpl GIMP palette file.
static QString colorToName(const QColor &color)
Returns a friendly display name for a color.
QList< QPair< QColor, QString > > QgsNamedColorList
List of colors paired with a friendly display name identifying the color.