QGIS API Documentation 3.41.0-Master (cea29feecf2)
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#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:5733
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 a 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.
This class is a composition of two QSettings instances:
Definition qgssettings.h:64
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.