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