25#include <QColorDialog>
32#include "moc_qgscolorschemelist.cpp"
34#ifdef ENABLE_MODELTEST
43#ifdef ENABLE_MODELTEST
44 new ModelTest( mModel,
this );
49 setItemDelegateForColumn( 0, mSwatchDelegate );
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 );
64 mModel->setScheme(
scheme, context, baseColor );
69 if ( !mScheme || !mScheme->isEditable() )
74 mScheme->setColors( mModel->colors(), mModel->context(), mModel->baseColor() );
81 const auto constSelectedIndexes = selectedIndexes();
82 for (
const QModelIndex &index : constSelectedIndexes )
87 QList<int> rowsToRemove = qgis::setToList( qgis::listToSet( rows ) );
90 std::sort( rowsToRemove.begin(), rowsToRemove.end(), std::greater<int>() );
91 const auto constRowsToRemove = rowsToRemove;
92 for (
const int row : constRowsToRemove )
94 mModel->removeRow( row );
100 mModel->addColor( color, label, allowDuplicate );
107 if ( pastedColors.length() == 0 )
114 QgsNamedColorList::const_iterator colorIt = pastedColors.constBegin();
115 for ( ; colorIt != pastedColors.constEnd(); ++colorIt )
124 const auto constSelectedIndexes = selectedIndexes();
125 for (
const QModelIndex &index : constSelectedIndexes )
130 const QList<int> rowsToCopy = qgis::setToList( qgis::listToSet( rows ) );
133 const auto constRowsToCopy = rowsToCopy;
134 for (
const int row : constRowsToCopy )
136 colorsToCopy << mModel->colors().at( row );
141 QApplication::clipboard()->setMimeData( mimeData );
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 (*.*)" ) );
150 if ( filePath.isEmpty() )
156 const QFileInfo fileInfo( filePath );
157 if ( !fileInfo.exists() || !fileInfo.isReadable() )
159 QMessageBox::critical(
nullptr, tr(
"Import Colors" ), tr(
"Error, file does not exist or is not readable." ) );
163 s.
setValue( QStringLiteral(
"/UI/lastGplPaletteDir" ), fileInfo.absolutePath() );
164 QFile file( filePath );
168 QMessageBox::critical(
nullptr, tr(
"Import Colors" ), tr(
"Error, no colors found in palette file." ) );
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)" ) );
179 if ( fileName.isEmpty() )
185 if ( !fileName.endsWith( QLatin1String(
".gpl" ), Qt::CaseInsensitive ) )
187 fileName += QLatin1String(
".gpl" );
190 const QFileInfo fileInfo( fileName );
191 s.
setValue( QStringLiteral(
"/UI/lastGplPaletteDir" ), fileInfo.absolutePath() );
193 QFile file( fileName );
197 QMessageBox::critical(
nullptr, tr(
"Export Colors" ), tr(
"Error writing palette file." ) );
205 if ( ( event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete ) )
208 const auto constSelectedIndexes = selectedIndexes();
209 for (
const QModelIndex &index : constSelectedIndexes )
214 QList<int> rowsToRemove = qgis::setToList( qgis::listToSet( rows ) );
217 std::sort( rowsToRemove.begin(), rowsToRemove.end(), std::greater<int>() );
218 const auto constRowsToRemove = rowsToRemove;
219 for (
const int row : constRowsToRemove )
221 mModel->removeRow( row );
226 QTreeView::keyPressEvent( event );
231 if ( event->button() == Qt::LeftButton )
234 mDragStartPosition =
event->pos();
236 QTreeView::mousePressEvent( event );
241 if ( ( event->button() == Qt::LeftButton ) && ( event->pos() - mDragStartPosition ).manhattanLength() <= QApplication::startDragDistance() )
247 if ( selectedIndexes().length() == mModel->columnCount() )
249 const QModelIndex selectedColor = selectedIndexes().at( 0 );
250 emit
colorSelected( mModel->colors().at( selectedColor.row() ).first );
254 QTreeView::mouseReleaseEvent( event );
268 if ( importedColors.length() == 0 )
275 QgsNamedColorList::const_iterator colorIt = importedColors.constBegin();
276 for ( ; colorIt != importedColors.constEnd(); ++colorIt )
296 return mModel->isDirty();
309 : QAbstractItemModel(
parent )
325 return QModelIndex();
328 if ( !
parent.isValid() && row >= 0 && row < mColors.size() )
331 return createIndex( row, column );
335 return QModelIndex();
343 return QModelIndex();
350 return mColors.size();
367 if ( !
index.isValid() )
370 const QPair<QColor, QString> namedColor = mColors.at(
index.row() );
373 case Qt::DisplayRole:
375 switch (
index.column() )
378 return namedColor.first;
380 return namedColor.second;
385 case Qt::TextAlignmentRole:
386 return static_cast<Qt::Alignment::Int
>( Qt::AlignLeft | Qt::AlignVCenter );
395 Qt::ItemFlags
flags = QAbstractItemModel::flags(
index );
397 if ( !
index.isValid() )
399 return flags | Qt::ItemIsDropEnabled;
402 switch (
index.column() )
406 if ( mScheme && mScheme->isEditable() )
410 return flags | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
412 return flags | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
420 if ( !mScheme || !mScheme->isEditable() )
423 if ( !
index.isValid() )
426 if (
index.row() >= mColors.length() )
429 switch (
index.column() )
432 mColors[
index.row()].first = value.value<QColor>();
438 mColors[
index.row()].second = value.toString();
452 case Qt::DisplayRole:
457 return tr(
"Color" );
459 return tr(
"Label" );
465 case Qt::TextAlignmentRole:
469 return static_cast<Qt::Alignment::Int
>( Qt::AlignHCenter | Qt::AlignVCenter );
471 return static_cast<Qt::Alignment::Int
>( Qt::AlignLeft | Qt::AlignVCenter );
476 return QAbstractItemModel::headerData( section, orientation, role );
482 if ( mScheme && mScheme->isEditable() )
484 return Qt::CopyAction | Qt::MoveAction;
488 return Qt::CopyAction;
494 if ( !mScheme || !mScheme->isEditable() )
496 return QStringList();
500 types << QStringLiteral(
"text/xml" );
501 types << QStringLiteral(
"text/plain" );
502 types << QStringLiteral(
"application/x-color" );
503 types << QStringLiteral(
"application/x-colorobject-list" );
511 QModelIndexList::const_iterator indexIt = indexes.constBegin();
512 for ( ; indexIt != indexes.constEnd(); ++indexIt )
514 if ( ( *indexIt ).column() > 0 )
517 colorList << qMakePair( mColors[( *indexIt ).row()].first, mColors[( *indexIt ).row()].second );
528 if ( !mScheme || !mScheme->isEditable() )
533 if ( action == Qt::IgnoreAction )
543 int beginRow = row != -1 ? row :
rowCount( QModelIndex() );
546 if ( droppedColors.length() == 0 )
553 QgsNamedColorList::const_iterator colorIt = droppedColors.constBegin();
554 for ( ; colorIt != droppedColors.constEnd(); ++colorIt )
557 const QPair<QColor, QString> color = qMakePair( ( *colorIt ).first, !( *colorIt ).second.isEmpty() ? ( *colorIt ).second :
QgsSymbolLayerUtils::colorToName( ( *colorIt ).first ) );
559 const int existingIndex = mColors.indexOf( color );
560 if ( existingIndex >= 0 )
562 if ( existingIndex < beginRow )
568 beginRemoveRows(
parent, existingIndex, existingIndex );
569 mColors.removeAt( existingIndex );
575 insertRows( beginRow, droppedColors.length(), QModelIndex() );
576 colorIt = droppedColors.constBegin();
577 for ( ; colorIt != droppedColors.constEnd(); ++colorIt )
579 const QModelIndex colorIdx =
index( beginRow, 0, QModelIndex() );
580 setData( colorIdx, QVariant( ( *colorIt ).first ) );
581 const QModelIndex labelIdx =
index( beginRow, 1, QModelIndex() );
597 mColors = scheme->
fetchColors( mContext, mBaseColor );
603 if ( !mScheme || !mScheme->isEditable() )
613 if ( row >= mColors.count() )
618 for (
int i = row + count - 1; i >= row; --i )
620 beginRemoveRows(
parent, i, i );
621 mColors.removeAt( i );
633 if ( !mScheme || !mScheme->isEditable() )
638 beginInsertRows( QModelIndex(), row, row + count - 1 );
639 for (
int i = row; i < row + count; ++i )
641 const QPair<QColor, QString> newColor;
642 mColors.insert( i, newColor );
651 if ( !mScheme || !mScheme->isEditable() )
656 if ( !allowDuplicate )
661 const int existingIndex = mColors.indexOf( newColor );
662 if ( existingIndex >= 0 )
664 beginRemoveRows( QModelIndex(), existingIndex, existingIndex );
665 mColors.removeAt( existingIndex );
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 ) );
684 : QAbstractItemDelegate( parent )
691 if ( option.state & QStyle::State_Selected )
693 painter->setPen( QPen( Qt::NoPen ) );
694 if ( option.state & QStyle::State_Active )
696 painter->setBrush( QBrush( option.widget->palette().highlight() ) );
700 painter->setBrush( QBrush( option.widget->palette().color( QPalette::Inactive, QPalette::Highlight ) ) );
702 painter->drawRect( option.rect );
705 QColor color = index.model()->data( index, Qt::DisplayRole ).value<QColor>();
706 if ( !color.isValid() )
711 QRect rect = option.rect;
714 const int cornerSize = iconSize / 6;
716 rect.setLeft( option.rect.center().x() - iconSize / 2 );
718 rect.setSize( QSize( iconSize, iconSize ) );
719 rect.adjust( 0, 1, 0, 1 );
722 painter->setRenderHint( QPainter::Antialiasing );
723 painter->setPen( Qt::NoPen );
724 if ( color.alpha() < 255 )
727 const QBrush checkBrush = QBrush( transparentBackground() );
728 painter->setBrush( checkBrush );
729 painter->drawRoundedRect( rect, cornerSize, cornerSize );
731 painter->setBrush( color );
732 painter->drawRoundedRect( rect, cornerSize, cornerSize );
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 );
742 painter->setBrush( color );
743 painter->drawRoundedRect( rect, cornerSize, cornerSize );
747QPixmap QgsColorSwatchDelegate::transparentBackground()
const
749 static QPixmap sTranspBkgrd;
751 if ( sTranspBkgrd.isNull() )
762 return QSize( iconSize, iconSize * 32 / 30.0 );
768 if ( event->type() == QEvent::MouseButtonDblClick )
770 if ( !index.model()->flags( index ).testFlag( Qt::ItemIsEditable ) )
776 const QColor color = index.model()->data( index, Qt::DisplayRole ).value<QColor>();
779 if ( panel && panel->dockMode() )
784 colorWidget->setProperty(
"index", index );
786 panel->openPanel( colorWidget );
791 if ( !newColor.isValid() )
796 return model->setData( index, newColor, Qt::EditRole );
802void QgsColorSwatchDelegate::colorChanged()
806 const QModelIndex index = colorWidget->property(
"index" ).toModelIndex();
807 const_cast<QAbstractItemModel *
>( index.model() )->setData( index, colorWidget->color(), Qt::EditRole );
static const double UI_SCALE_FACTOR
UI scaling factor.
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
Scoped object for saving and restoring a QPainter object's state.
Stores settings for use within QGIS.
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.