46 #include <QColorDialog>
48 #include <QStandardItemModel>
49 #include <QInputDialog>
50 #include <QMessageBox>
56 #include <QStandardItem>
60 static const int SYMBOL_LAYER_ITEM_TYPE = QStandardItem::UserType + 1;
70 mDDSize = mMarker->dataDefinedSize();
71 mDDAngle = mMarker->dataDefinedAngle();
73 if ( !mDDSize && !mDDAngle )
80 mDDWidth = mLine->dataDefinedWidth();
88 void DataDefinedRestorer::save()
92 mSize = mMarkerSymbolLayer->size();
93 mAngle = mMarkerSymbolLayer->angle();
94 mMarkerOffset = mMarkerSymbolLayer->offset();
98 mWidth = mLineSymbolLayer->width();
99 mLineOffset = mLineSymbolLayer->offset();
103 void DataDefinedRestorer::restore()
108 ( mSize != mMarkerSymbolLayer->size() || mMarkerOffset != mMarkerSymbolLayer->offset() ) )
109 mMarker->setDataDefinedSize( mDDSize );
111 mAngle != mMarkerSymbolLayer->angle() )
112 mMarker->setDataDefinedAngle( mDDAngle );
117 ( mWidth != mLineSymbolLayer->width() || mLineOffset != mLineSymbolLayer->offset() ) )
118 mLine->setDataDefinedWidth( mDDWidth );
125 class SymbolLayerItem :
public QStandardItem
130 setLayer( layer, symbolType );
133 explicit SymbolLayerItem(
QgsSymbol *symbol )
143 mSymbolType = symbolType;
157 if ( !mSize.isValid() )
160 mSize = QSize( size, size );
169 if (
auto *lParent = parent() )
170 static_cast<SymbolLayerItem *
>( lParent )->updatePreview();
173 int type()
const override {
return SYMBOL_LAYER_ITEM_TYPE; }
174 bool isLayer() {
return mIsLayer; }
187 QVariant data(
int role )
const override
189 if ( role == Qt::DisplayRole || role == Qt::EditRole )
201 switch ( mSymbol->type() )
204 return QCoreApplication::translate(
"SymbolLayerItem",
"Marker" );
206 return QCoreApplication::translate(
"SymbolLayerItem",
"Fill" );
208 return QCoreApplication::translate(
"SymbolLayerItem",
"Line" );
214 else if ( role == Qt::ForegroundRole && mIsLayer )
216 if ( !mLayer->enabled() )
218 QPalette
pal = qApp->palette();
219 QBrush brush = QStandardItem::data( role ).value< QBrush >();
220 brush.setColor(
pal.color( QPalette::Disabled, QPalette::WindowText ) );
231 if ( role == Qt::CheckStateRole )
233 return QStandardItem::data( role );
255 setWindowModality( Qt::WindowModal );
259 this->layout()->setContentsMargins( 0, 0, 0, 0 );
261 layersTree->setMaximumHeight(
static_cast< int >(
Qgis::UI_SCALE_FACTOR * fontMetrics().height() * 7 ) );
262 layersTree->setMinimumHeight( layersTree->maximumHeight() );
263 lblPreview->setMaximumWidth( layersTree->maximumHeight() );
271 iconLock.addFile(
QgsApplication::iconPath( QStringLiteral(
"unlocked.svg" ) ), QSize(), QIcon::Normal, QIcon::Off );
272 iconLock.addFile(
QgsApplication::iconPath( QStringLiteral(
"unlocked.svg" ) ), QSize(), QIcon::Active, QIcon::Off );
273 btnLock->setIcon( iconLock );
278 mSymbolLayersModel =
new QStandardItemModel( layersTree );
280 layersTree->setModel( mSymbolLayersModel );
281 layersTree->setHeaderHidden(
true );
286 #if 0 // this is too expensive to do for many providers. TODO revisit when support for connection timeouts is complete across all providers
293 mPreviewExpressionContext.
setFeature( mPreviewFeature );
301 QItemSelectionModel *selModel = layersTree->selectionModel();
304 loadSymbol( mSymbol,
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->invisibleRootItem() ) );
318 const QModelIndex newIndex = layersTree->model()->index( 0, 0 );
319 layersTree->setCurrentIndex( newIndex );
346 if ( !mAdvancedMenu )
348 mAdvancedMenu =
new QMenu(
this );
352 return mAdvancedMenu;
361 mPreviewExpressionContext = *lExpressionContext;
365 mPreviewExpressionContext.
setFeature( mPreviewFeature );
368 QWidget *widget = stackedWidget->currentWidget();
370 layerProp->setContext(
context );
372 listWidget->setContext(
context );
391 mSymbolLayersModel->clear();
392 parent =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->invisibleRootItem() );
395 SymbolLayerItem *symbolItem =
new SymbolLayerItem(
symbol );
396 QFont boldFont = symbolItem->font();
397 boldFont.setBold(
true );
398 symbolItem->setFont( boldFont );
399 parent->appendRow( symbolItem );
402 for (
int i = count - 1; i >= 0; i-- )
405 layerItem->setEditable(
false );
406 symbolItem->appendRow( layerItem );
411 layersTree->setExpanded( layerItem->index(),
true );
413 layersTree->setExpanded( symbolItem->index(),
true );
415 if ( mSymbol ==
symbol && !layersTree->currentIndex().isValid() )
418 layersTree->setCurrentIndex( symbolItem->index() );
422 void QgsSymbolSelectorWidget::reloadSymbol()
424 mSymbolLayersModel->clear();
425 loadSymbol( mSymbol,
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->invisibleRootItem() ) );
428 void QgsSymbolSelectorWidget::updateUi()
430 const QModelIndex currentIdx = layersTree->currentIndex();
431 if ( !currentIdx.isValid() )
434 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( currentIdx ) );
435 if ( !item->isLayer() )
437 btnUp->setEnabled(
false );
438 btnDown->setEnabled(
false );
439 btnRemoveLayer->setEnabled(
false );
440 btnLock->setEnabled(
false );
441 btnDuplicate->setEnabled(
false );
445 const int rowCount = item->parent()->rowCount();
446 const int currentRow = item->row();
448 btnUp->setEnabled( currentRow > 0 );
449 btnDown->setEnabled( currentRow < rowCount - 1 );
450 btnRemoveLayer->setEnabled( rowCount > 1 );
451 btnLock->setEnabled(
true );
452 btnDuplicate->setEnabled(
true );
460 std::unique_ptr< QgsSymbol > symbolClone( mSymbol->
clone() );
461 const QImage preview = symbolClone->bigSymbolPreviewImage( &mPreviewExpressionContext, Qgis::SymbolPreviewFlags() );
462 lblPreview->setPixmap( QPixmap::fromImage( preview ) );
464 if ( !mBlockModified )
471 SymbolLayerItem *item = currentLayerItem();
473 item->updatePreview();
478 SymbolLayerItem *QgsSymbolSelectorWidget::currentLayerItem()
480 const QModelIndex idx = layersTree->currentIndex();
481 if ( !idx.isValid() )
484 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( idx ) );
485 if ( !item->isLayer() )
493 const QModelIndex idx = layersTree->currentIndex();
494 if ( !idx.isValid() )
497 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( idx ) );
498 if ( item->isLayer() )
499 return item->layer();
508 SymbolLayerItem *currentItem =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( layersTree->currentIndex() ) );
512 if ( currentItem->isLayer() )
514 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( currentItem->parent() );
515 mDataDefineRestorer.reset(
new DataDefinedRestorer( parent->symbol(), currentItem->layer() ) );
519 setWidget( layerProp );
530 mDataDefineRestorer.reset();
532 currentItem->symbol()->setLayer( mVectorLayer );
536 symbolsList->setContext( mContext );
538 setWidget( symbolsList );
546 SymbolLayerItem *currentItem =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( layersTree->currentIndex() ) );
547 if ( !currentItem || currentItem->isLayer() )
551 if ( currentItem->parent() )
555 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( currentItem->parent() );
556 parent->removeRow( 0 );
558 layersTree->setCurrentIndex( parent->child( 0 )->index() );
559 parent->updatePreview();
565 const QModelIndex newIndex = layersTree->model()->index( 0, 0 );
566 layersTree->setCurrentIndex( newIndex );
573 void QgsSymbolSelectorWidget::setWidget( QWidget *widget )
575 const int index = stackedWidget->addWidget( widget );
576 stackedWidget->setCurrentIndex( index );
577 if ( mPresentWidget )
578 mPresentWidget->deleteLater();
579 mPresentWidget = widget;
582 void QgsSymbolSelectorWidget::updateLockButton()
587 btnLock->setChecked( layer->
isLocked() );
592 const QModelIndex idx = layersTree->currentIndex();
593 if ( !idx.isValid() )
597 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( idx ) );
598 if ( item->isLayer() )
600 insertIdx = item->row();
601 item =
static_cast<SymbolLayerItem *
>( item->parent() );
604 QgsSymbol *parentSymbol = item->symbol();
618 if ( insertIdx == -1 )
625 static_cast<QgsMarkerSymbol *
>( parentSymbol )->setDataDefinedSize( ddSize );
627 static_cast<QgsMarkerSymbol *
>( parentSymbol )->setDataDefinedAngle( ddAngle );
629 static_cast<QgsLineSymbol *
>( parentSymbol )->setDataDefinedWidth( ddWidth );
631 SymbolLayerItem *newLayerItem =
new SymbolLayerItem( newLayer, parentSymbol->
type() );
632 item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
633 item->updatePreview();
635 layersTree->setCurrentIndex( mSymbolLayersModel->indexFromItem( newLayerItem ) );
642 SymbolLayerItem *item = currentLayerItem();
643 const int row = item->row();
644 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( item->parent() );
646 const int layerIdx = parent->rowCount() - row - 1;
647 QgsSymbol *parentSymbol = parent->symbol();
650 parent->removeRow( row );
651 parent->updatePreview();
653 const QModelIndex newIdx = parent->child( 0 )->index();
654 layersTree->setCurrentIndex( newIdx );
664 moveLayerByOffset( + 1 );
669 moveLayerByOffset( -1 );
672 void QgsSymbolSelectorWidget::moveLayerByOffset(
int offset )
674 SymbolLayerItem *item = currentLayerItem();
677 const int row = item->row();
679 SymbolLayerItem *parent =
static_cast<SymbolLayerItem *
>( item->parent() );
680 QgsSymbol *parentSymbol = parent->symbol();
682 const int layerIdx = parent->rowCount() - row - 1;
687 QList<QStandardItem *> rowItems = parent->takeRow( row );
688 parent->insertRows( row + offset, rowItems );
689 parent->updatePreview();
691 const QModelIndex newIdx = rowItems[ 0 ]->index();
692 layersTree->setCurrentIndex( newIdx );
703 layer->
setLocked( btnLock->isChecked() );
709 const QModelIndex idx = layersTree->currentIndex();
710 if ( !idx.isValid() )
713 SymbolLayerItem *item =
static_cast<SymbolLayerItem *
>( mSymbolLayersModel->itemFromIndex( idx ) );
714 if ( !item->isLayer() )
719 const int insertIdx = item->row();
720 item =
static_cast<SymbolLayerItem *
>( item->parent() );
722 QgsSymbol *parentSymbol = item->symbol();
725 if ( insertIdx == -1 )
730 SymbolLayerItem *newLayerItem =
new SymbolLayerItem( newLayer, parentSymbol->
type() );
731 item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
735 layersTree->setExpanded( newLayerItem->index(),
true );
737 item->updatePreview();
739 layersTree->setCurrentIndex( mSymbolLayersModel->indexFromItem( newLayerItem ) );
746 SymbolLayerItem *item = currentLayerItem();
751 item->removeRow( 0 );
761 layersTree->setExpanded( item->index(),
true );
765 const int layerIdx = item->parent()->rowCount() - item->row() - 1;
768 item->updatePreview();
777 setLayout(
new QVBoxLayout() );
780 mButtonBox =
new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok );
782 connect( mButtonBox, &QDialogButtonBox::accepted,
this, &QDialog::accept );
783 connect( mButtonBox, &QDialogButtonBox::rejected,
this, &QDialog::reject );
784 connect( mButtonBox, &QDialogButtonBox::helpRequested,
this, &QgsSymbolSelectorDialog::showHelp );
786 layout()->addWidget( mSelectorWidget );
787 layout()->addWidget( mButtonBox );
791 mSelectorWidget->setMinimumSize( 460, 560 );
792 setObjectName( QStringLiteral(
"SymbolSelectorDialog" ) );
799 layout()->setContentsMargins( 0, 0, 0, 0 );
803 setWindowTitle( tr(
"Symbol Selector" ) );
825 return mSelectorWidget->
symbol();
831 if ( !isWindow() && e->key() == Qt::Key_Escape )
837 QDialog::keyPressEvent( e );
841 void QgsSymbolSelectorDialog::reloadSymbol()
843 mSelectorWidget->reloadSymbol();
851 void QgsSymbolSelectorDialog::updateUi()
853 mSelectorWidget->updateUi();
856 void QgsSymbolSelectorDialog::updateLockButton()
858 mSelectorWidget->updateLockButton();
861 SymbolLayerItem *QgsSymbolSelectorDialog::currentLayerItem()
863 return mSelectorWidget->currentLayerItem();
868 return mSelectorWidget->currentLayer();
871 void QgsSymbolSelectorDialog::moveLayerByOffset(
int offset )
873 mSelectorWidget->moveLayerByOffset( offset );
876 void QgsSymbolSelectorDialog::setWidget( QWidget *widget )
878 mSelectorWidget->setWidget( widget );
941 void QgsSymbolSelectorDialog::showHelp()
946 void QgsSymbolSelectorWidget::projectDataChanged()
948 mBlockModified =
true;
951 mBlockModified =
false;
954 void QgsSymbolSelectorWidget::layersAboutToBeRemoved(
const QList<QgsMapLayer *> &layers )
956 if ( mVectorLayer && layers.contains( mVectorLayer ) )