QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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 "qgsapplication.h"
18#include "qgslogger.h"
19#include "qgssymbollayerutils.h"
20#include "qgscolordialog.h"
21#include "qgssettings.h"
22
23#include <QPainter>
24#include <QColorDialog>
25#include <QMimeData>
26#include <QClipboard>
27#include <QKeyEvent>
28#include <QFileDialog>
29#include <QMessageBox>
30
31#ifdef ENABLE_MODELTEST
32#include "modeltest.h"
33#endif
34
35QgsColorSchemeList::QgsColorSchemeList( QWidget *parent, QgsColorScheme *scheme, const QString &context, const QColor &baseColor )
36 : QTreeView( parent )
37 , mScheme( scheme )
38{
39 mModel = new QgsColorSchemeModel( scheme, context, baseColor, this );
40#ifdef ENABLE_MODELTEST
41 new ModelTest( mModel, this );
42#endif
43 setModel( mModel );
44
45 mSwatchDelegate = new QgsColorSwatchDelegate( this );
46 setItemDelegateForColumn( 0, mSwatchDelegate );
47
48 setRootIsDecorated( false );
49 setSelectionMode( QAbstractItemView::ExtendedSelection );
50 setSelectionBehavior( QAbstractItemView::SelectRows );
51 setDragEnabled( true );
52 setAcceptDrops( true );
53 setDragDropMode( QTreeView::DragDrop );
54 setDropIndicatorShown( true );
55 setDefaultDropAction( Qt::CopyAction );
56}
57
58void QgsColorSchemeList::setScheme( QgsColorScheme *scheme, const QString &context, const QColor &baseColor )
59{
60 mScheme = scheme;
61 mModel->setScheme( scheme, context, baseColor );
62}
63
65{
66 if ( !mScheme || !mScheme->isEditable() )
67 {
68 return false;
69 }
70
71 mScheme->setColors( mModel->colors(), mModel->context(), mModel->baseColor() );
72 return true;
73}
74
76{
77 QList<int> rows;
78 const auto constSelectedIndexes = selectedIndexes();
79 for ( const QModelIndex &index : constSelectedIndexes )
80 {
81 rows << index.row();
82 }
83 //remove duplicates
84 QList<int> rowsToRemove = qgis::setToList( qgis::listToSet( rows ) );
85
86 //remove rows in descending order
87 std::sort( rowsToRemove.begin(), rowsToRemove.end(), std::greater<int>() );
88 const auto constRowsToRemove = rowsToRemove;
89 for ( const int row : constRowsToRemove )
90 {
91 mModel->removeRow( row );
92 }
93}
94
95void QgsColorSchemeList::addColor( const QColor &color, const QString &label, bool allowDuplicate )
96{
97 mModel->addColor( color, label, allowDuplicate );
98}
99
101{
102 const QgsNamedColorList pastedColors = QgsSymbolLayerUtils::colorListFromMimeData( QApplication::clipboard()->mimeData() );
103
104 if ( pastedColors.length() == 0 )
105 {
106 //no pasted colors
107 return;
108 }
109
110 //insert pasted colors
111 QgsNamedColorList::const_iterator colorIt = pastedColors.constBegin();
112 for ( ; colorIt != pastedColors.constEnd(); ++colorIt )
113 {
114 mModel->addColor( ( *colorIt ).first, !( *colorIt ).second.isEmpty() ? ( *colorIt ).second : QgsSymbolLayerUtils::colorToName( ( *colorIt ).first ) );
115 }
116}
117
119{
120 QList<int> rows;
121 const auto constSelectedIndexes = selectedIndexes();
122 for ( const QModelIndex &index : constSelectedIndexes )
123 {
124 rows << index.row();
125 }
126 //remove duplicates
127 const QList<int> rowsToCopy = qgis::setToList( qgis::listToSet( rows ) );
128
129 QgsNamedColorList colorsToCopy;
130 const auto constRowsToCopy = rowsToCopy;
131 for ( const int row : constRowsToCopy )
132 {
133 colorsToCopy << mModel->colors().at( row );
134 }
135
136 //copy colors
137 QMimeData *mimeData = QgsSymbolLayerUtils::colorListToMimeData( colorsToCopy );
138 QApplication::clipboard()->setMimeData( mimeData );
139}
140
142{
143 QgsSettings s;
144 const QString lastDir = s.value( QStringLiteral( "/UI/lastGplPaletteDir" ), QDir::homePath() ).toString();
145 const QString filePath = QFileDialog::getOpenFileName( this, tr( "Select Palette File" ), lastDir, QStringLiteral( "GPL (*.gpl);;All files (*.*)" ) );
146 activateWindow();
147 if ( filePath.isEmpty() )
148 {
149 return;
150 }
151
152 //check if file exists
153 const QFileInfo fileInfo( filePath );
154 if ( !fileInfo.exists() || !fileInfo.isReadable() )
155 {
156 QMessageBox::critical( nullptr, tr( "Import Colors" ), tr( "Error, file does not exist or is not readable." ) );
157 return;
158 }
159
160 s.setValue( QStringLiteral( "/UI/lastGplPaletteDir" ), fileInfo.absolutePath() );
161 QFile file( filePath );
162 const bool importOk = importColorsFromGpl( file );
163 if ( !importOk )
164 {
165 QMessageBox::critical( nullptr, tr( "Import Colors" ), tr( "Error, no colors found in palette file." ) );
166 return;
167 }
168}
169
171{
172 QgsSettings s;
173 const QString lastDir = s.value( QStringLiteral( "/UI/lastGplPaletteDir" ), QDir::homePath() ).toString();
174 QString fileName = QFileDialog::getSaveFileName( this, tr( "Palette file" ), lastDir, QStringLiteral( "GPL (*.gpl)" ) );
175 activateWindow();
176 if ( fileName.isEmpty() )
177 {
178 return;
179 }
180
181 // ensure filename contains extension
182 if ( !fileName.endsWith( QLatin1String( ".gpl" ), Qt::CaseInsensitive ) )
183 {
184 fileName += QLatin1String( ".gpl" );
185 }
186
187 const QFileInfo fileInfo( fileName );
188 s.setValue( QStringLiteral( "/UI/lastGplPaletteDir" ), fileInfo.absolutePath() );
189
190 QFile file( fileName );
191 const bool exportOk = exportColorsToGpl( file );
192 if ( !exportOk )
193 {
194 QMessageBox::critical( nullptr, tr( "Export Colors" ), tr( "Error writing palette file." ) );
195 return;
196 }
197}
198
199void QgsColorSchemeList::keyPressEvent( QKeyEvent *event )
200{
201 //listen out for delete/backspace presses and remove selected colors
202 if ( ( event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete ) )
203 {
204 QList<int> rows;
205 const auto constSelectedIndexes = selectedIndexes();
206 for ( const QModelIndex &index : constSelectedIndexes )
207 {
208 rows << index.row();
209 }
210 //remove duplicates
211 QList<int> rowsToRemove = qgis::setToList( qgis::listToSet( rows ) );
212
213 //remove rows in descending order
214 std::sort( rowsToRemove.begin(), rowsToRemove.end(), std::greater<int>() );
215 const auto constRowsToRemove = rowsToRemove;
216 for ( const int row : constRowsToRemove )
217 {
218 mModel->removeRow( row );
219 }
220 return;
221 }
222
223 QTreeView::keyPressEvent( event );
224}
225
226void QgsColorSchemeList::mousePressEvent( QMouseEvent *event )
227{
228 if ( event->button() == Qt::LeftButton )
229 {
230 //record press start position
231 mDragStartPosition = event->pos();
232 }
233 QTreeView::mousePressEvent( event );
234}
235
237{
238 if ( ( event->button() == Qt::LeftButton ) &&
239 ( 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}
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,
701 QPalette::Highlight ) ) );
702 }
703 painter->drawRect( option.rect );
704 }
705
706 const QColor color = index.model()->data( index, Qt::DisplayRole ).value<QColor>();
707 if ( !color.isValid() )
708 {
709 return;
710 }
711
712 QRect rect = option.rect;
713 const int iconSize = Qgis::UI_SCALE_FACTOR * option.fontMetrics.horizontalAdvance( 'X' ) * 4;
714
715 const int cornerSize = iconSize / 6;
716 //center it
717 rect.setLeft( option.rect.center().x() - iconSize / 2 );
718
719 rect.setSize( QSize( iconSize, iconSize ) );
720 rect.adjust( 0, 1, 0, 1 );
721 //create an icon pixmap
722 const QgsScopedQPainterState painterState( painter );
723 painter->setRenderHint( QPainter::Antialiasing );
724 painter->setPen( Qt::NoPen );
725 if ( color.alpha() < 255 )
726 {
727 //start with checkboard pattern
728 const QBrush checkBrush = QBrush( transparentBackground() );
729 painter->setBrush( checkBrush );
730 painter->drawRoundedRect( rect, cornerSize, cornerSize );
731 }
732
733 //draw semi-transparent color on top
734 painter->setBrush( color );
735 painter->drawRoundedRect( rect, cornerSize, cornerSize );
736}
737
738QPixmap QgsColorSwatchDelegate::transparentBackground() const
739{
740 static QPixmap sTranspBkgrd;
741
742 if ( sTranspBkgrd.isNull() )
743 sTranspBkgrd = QgsApplication::getThemePixmap( QStringLiteral( "/transp-background_8x8.png" ) );
744
745 return sTranspBkgrd;
746}
747
748QSize QgsColorSwatchDelegate::sizeHint( const QStyleOptionViewItem &option, const QModelIndex &index ) const
749{
750 Q_UNUSED( index )
751
752 const int iconSize = Qgis::UI_SCALE_FACTOR * option.fontMetrics.horizontalAdvance( 'X' ) * 4;
753 return QSize( iconSize, iconSize * 32 / 30.0 );
754}
755
756bool QgsColorSwatchDelegate::editorEvent( QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index )
757{
758 Q_UNUSED( option )
759 if ( event->type() == QEvent::MouseButtonDblClick )
760 {
761 if ( !index.model()->flags( index ).testFlag( Qt::ItemIsEditable ) )
762 {
763 //item not editable
764 return false;
765 }
766
767 const QColor color = index.model()->data( index, Qt::DisplayRole ).value<QColor>();
768
769 QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( qobject_cast< QWidget * >( parent() ) );
770 if ( panel && panel->dockMode() )
771 {
773 colorWidget->setPanelTitle( tr( "Select Color" ) );
774 colorWidget->setAllowOpacity( true );
775 colorWidget->setProperty( "index", index );
776 connect( colorWidget, &QgsCompoundColorWidget::currentColorChanged, this, &QgsColorSwatchDelegate::colorChanged );
777 panel->openPanel( colorWidget );
778 return true;
779 }
780
781 const QColor newColor = QgsColorDialog::getColor( color, mParent, tr( "Select color" ), true );
782 if ( !newColor.isValid() )
783 {
784 return false;
785 }
786
787 return model->setData( index, newColor, Qt::EditRole );
788 }
789
790 return false;
791}
792
793void QgsColorSwatchDelegate::colorChanged()
794{
795 if ( QgsCompoundColorWidget *colorWidget = qobject_cast< QgsCompoundColorWidget * >( sender() ) )
796 {
797 const QModelIndex index = colorWidget->property( "index" ).toModelIndex();
798 const_cast< QAbstractItemModel * >( index.model() )->setData( index, colorWidget->color(), Qt::EditRole );
799 }
800}
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition: qgis.h:4927
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.
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window's toolbar icons.