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