27 #include <QAbstractListModel>
28 #include <QInputDialog>
36 : QAbstractListModel( parent )
41 int QgsVectorTileBasicRendererListModel::rowCount(
const QModelIndex &parent )
const
43 if ( parent.isValid() )
46 return mRenderer->styles().count();
49 int QgsVectorTileBasicRendererListModel::columnCount(
const QModelIndex & )
const
54 QVariant QgsVectorTileBasicRendererListModel::data(
const QModelIndex &index,
int role )
const
56 if ( index.row() < 0 || index.row() >= mRenderer->styles().count() )
59 const QList<QgsVectorTileBasicRendererStyle> styles = mRenderer->styles();
67 if ( index.column() == 0 )
69 else if ( index.column() == 1 )
70 return style.
layerName().isEmpty() ? tr(
"(all layers)" ) : style.layerName();
71 else if ( index.column() == 2 )
73 else if ( index.column() == 3 )
75 else if ( index.column() == 4 )
76 return style.
filterExpression().isEmpty() ? tr(
"(no filter)" ) : style.filterExpression();
83 if ( index.column() == 0 )
85 else if ( index.column() == 1 )
87 else if ( index.column() == 2 )
89 else if ( index.column() == 3 )
91 else if ( index.column() == 4 )
97 case Qt::DecorationRole:
99 if ( index.column() == 0 && style.
symbol() )
107 case Qt::CheckStateRole:
109 if ( index.column() != 0 )
111 return style.
isEnabled() ? Qt::Checked : Qt::Unchecked;
133 QVariant QgsVectorTileBasicRendererListModel::headerData(
int section, Qt::Orientation orientation,
int role )
const
135 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 && section < 5 )
138 lst << tr(
"Label" ) << tr(
"Layer" ) << tr(
"Min. Zoom" ) << tr(
"Max. Zoom" ) << tr(
"Filter" );
145 Qt::ItemFlags QgsVectorTileBasicRendererListModel::flags(
const QModelIndex &index )
const
147 if ( !index.isValid() )
148 return Qt::ItemIsDropEnabled;
150 const Qt::ItemFlag checkable = ( index.column() == 0 ? Qt::ItemIsUserCheckable : Qt::NoItemFlags );
152 return Qt::ItemIsEnabled | Qt::ItemIsSelectable |
153 Qt::ItemIsEditable | checkable |
154 Qt::ItemIsDragEnabled;
157 bool QgsVectorTileBasicRendererListModel::setData(
const QModelIndex &index,
const QVariant &value,
int role )
159 if ( !index.isValid() )
164 if ( role == Qt::CheckStateRole )
166 style.
setEnabled( value.toInt() == Qt::Checked );
167 mRenderer->setStyle( index.row(), style );
168 emit dataChanged( index, index );
172 if ( role == Qt::EditRole )
174 if ( index.column() == 0 )
176 else if ( index.column() == 1 )
178 else if ( index.column() == 2 )
180 else if ( index.column() == 3 )
182 else if ( index.column() == 4 )
185 mRenderer->setStyle( index.row(), style );
186 emit dataChanged( index, index );
193 bool QgsVectorTileBasicRendererListModel::removeRows(
int row,
int count,
const QModelIndex &parent )
195 QList<QgsVectorTileBasicRendererStyle> styles = mRenderer->styles();
197 if ( row < 0 || row >= styles.count() )
200 beginRemoveRows( parent, row, row + count - 1 );
202 for (
int i = 0; i < count; i++ )
204 if ( row < styles.count() )
206 styles.removeAt( row );
210 mRenderer->setStyles( styles );
218 beginInsertRows( QModelIndex(), row, row );
220 QList<QgsVectorTileBasicRendererStyle> styles = mRenderer->styles();
221 styles.insert( row, style );
222 mRenderer->setStyles( styles );
227 Qt::DropActions QgsVectorTileBasicRendererListModel::supportedDropActions()
const
229 return Qt::MoveAction;
232 QStringList QgsVectorTileBasicRendererListModel::mimeTypes()
const
235 types << QStringLiteral(
"application/vnd.text.list" );
239 QMimeData *QgsVectorTileBasicRendererListModel::mimeData(
const QModelIndexList &indexes )
const
241 QMimeData *mimeData =
new QMimeData();
242 QByteArray encodedData;
244 QDataStream stream( &encodedData, QIODevice::WriteOnly );
246 const auto constIndexes = indexes;
247 for (
const QModelIndex &index : constIndexes )
250 if ( !index.isValid() || index.column() != 0 )
256 QDomElement rootElem = doc.createElement( QStringLiteral(
"vector_tile_basic_renderer_style_mime" ) );
258 doc.appendChild( rootElem );
260 stream << doc.toString( -1 );
263 mimeData->setData( QStringLiteral(
"application/vnd.text.list" ), encodedData );
267 bool QgsVectorTileBasicRendererListModel::dropMimeData(
const QMimeData *data,
268 Qt::DropAction action,
int row,
int column,
const QModelIndex &parent )
272 if ( action == Qt::IgnoreAction )
275 if ( !data->hasFormat( QStringLiteral(
"application/vnd.text.list" ) ) )
278 if ( parent.column() > 0 )
281 QByteArray encodedData = data->data( QStringLiteral(
"application/vnd.text.list" ) );
282 QDataStream stream( &encodedData, QIODevice::ReadOnly );
288 row = rowCount( parent );
291 while ( !stream.atEnd() )
297 if ( !doc.setContent( text ) )
299 const QDomElement rootElem = doc.documentElement();
300 if ( rootElem.tagName() != QLatin1String(
"vector_tile_basic_renderer_style_mime" ) )
306 insertStyle( row + rows, style );
318 , mMapCanvas( canvas )
319 , mMessageBar( messageBar )
322 layout()->setContentsMargins( 0, 0, 0, 0 );
324 mFilterLineEdit->setShowClearButton(
true );
325 mFilterLineEdit->setShowSearchIcon(
true );
326 mFilterLineEdit->setPlaceholderText( tr(
"Filter rules" ) );
328 QMenu *menuAddRule =
new QMenu( btnAddRule );
332 btnAddRule->setMenu( menuAddRule );
334 connect( btnEditRule, &QPushButton::clicked,
this, &QgsVectorTileBasicRendererWidget::editStyle );
335 connect( btnRemoveRule, &QAbstractButton::clicked,
this, &QgsVectorTileBasicRendererWidget::removeStyle );
337 connect( viewStyles, &QAbstractItemView::doubleClicked,
this, &QgsVectorTileBasicRendererWidget::editStyleAtIndex );
344 const double tileScale = mVTLayer ? mVTLayer->tileMatrixSet().calculateTileScaleForMap( mMapCanvas->scale(),
350 mLabelCurrentZoom->setText( tr(
"Current zoom: %1" ).arg( zoom ) );
352 mProxyModel->setCurrentZoom( zoom );
356 const double tileScale = mVTLayer ? mVTLayer->tileMatrixSet().calculateTileScaleForMap( mMapCanvas->scale(),
357 mapSettings.destinationCrs(),
358 mapSettings.visibleExtent(),
359 mapSettings.outputSize(),
360 mapSettings.outputDpi() ) : mMapCanvas->
scale();
361 mLabelCurrentZoom->setText( tr(
"Current zoom: %1" ).arg( mVTLayer ? mVTLayer->tileMatrixSet().scaleToZoomLevel( tileScale ) :
QgsVectorTileUtils::scaleToZoomLevel( tileScale, 0, 99 ) ) );
364 connect( mCheckVisibleOnly, &QCheckBox::toggled,
this, [ = ](
bool filter )
366 mProxyModel->setFilterVisible( filter );
369 connect( mFilterLineEdit, &QgsFilterLineEdit::textChanged,
this, [ = ](
const QString & text )
371 mProxyModel->setFilterString( text );
390 mModel =
new QgsVectorTileBasicRendererListModel( mRenderer.get(), viewStyles );
391 mProxyModel =
new QgsVectorTileBasicRendererProxyModel( mModel, viewStyles );
392 viewStyles->setModel( mProxyModel );
397 const double tileScale = mVTLayer ? mVTLayer->tileMatrixSet().calculateTileScaleForMap( mMapCanvas->scale(),
403 mProxyModel->setCurrentZoom( zoom );
411 QgsVectorTileBasicRendererWidget::~QgsVectorTileBasicRendererWidget() =
default;
413 void QgsVectorTileBasicRendererWidget::apply()
415 mVTLayer->setRenderer( mRenderer->clone() );
439 const int rows = mModel->rowCount();
440 mModel->insertStyle( rows, style );
441 viewStyles->selectionModel()->setCurrentIndex( mProxyModel->mapFromSource( mModel->index( rows, 0 ) ), QItemSelectionModel::ClearAndSelect );
444 void QgsVectorTileBasicRendererWidget::editStyle()
446 editStyleAtIndex( viewStyles->selectionModel()->currentIndex() );
449 void QgsVectorTileBasicRendererWidget::editStyleAtIndex(
const QModelIndex &proxyIndex )
451 const QModelIndex index = mProxyModel->mapToSource( proxyIndex );
452 if ( index.row() < 0 || index.row() >= mRenderer->styles().count() )
460 std::unique_ptr< QgsSymbol > symbol( style.
symbol()->
clone() );
469 const double tileScale = mVTLayer ? mVTLayer->tileMatrixSet().calculateTileScaleForMap( mMapCanvas->scale(),
499 if ( !dlg.exec() || !symbol )
505 mRenderer->setStyle( index.row(), style );
506 emit widgetChanged();
510 void QgsVectorTileBasicRendererWidget::updateSymbolsFromWidget()
512 const int index = mProxyModel->mapToSource( viewStyles->selectionModel()->currentIndex() ).row();
521 mRenderer->setStyle( index, style );
522 emit widgetChanged();
525 void QgsVectorTileBasicRendererWidget::cleanUpSymbolSelector(
QgsPanelWidget *container )
534 void QgsVectorTileBasicRendererWidget::removeStyle()
536 const QModelIndexList sel = viewStyles->selectionModel()->selectedIndexes();
539 for (
const QModelIndex &proxyIndex : sel )
541 const QModelIndex sourceIndex = mProxyModel->mapToSource( proxyIndex );
542 if ( !res.contains( sourceIndex.row() ) )
543 res << sourceIndex.row();
545 std::sort( res.begin(), res.end() );
547 for (
int i = res.size() - 1; i >= 0; --i )
549 mModel->removeRow( res[ i ] );
552 viewStyles->selectionModel()->clear();
555 QgsVectorTileBasicRendererProxyModel::QgsVectorTileBasicRendererProxyModel( QgsVectorTileBasicRendererListModel *source, QObject *parent )
556 : QSortFilterProxyModel( parent )
558 setSourceModel( source );
559 setDynamicSortFilter(
true );
562 void QgsVectorTileBasicRendererProxyModel::setCurrentZoom(
int zoom )
568 void QgsVectorTileBasicRendererProxyModel::setFilterVisible(
bool enabled )
570 mFilterVisible = enabled;
574 void QgsVectorTileBasicRendererProxyModel::setFilterString(
const QString &
string )
576 mFilterString = string;
580 bool QgsVectorTileBasicRendererProxyModel::filterAcceptsRow(
int source_row,
const QModelIndex &source_parent )
const
582 if ( mCurrentZoom >= 0 && mFilterVisible )
584 const int rowMinZoom = sourceModel()->data( sourceModel()->index( source_row, 0, source_parent ), QgsVectorTileBasicRendererListModel::MinZoom ).toInt();
585 const int rowMaxZoom = sourceModel()->data( sourceModel()->index( source_row, 0, source_parent ), QgsVectorTileBasicRendererListModel::MaxZoom ).toInt();
587 if ( rowMinZoom >= 0 && rowMinZoom > mCurrentZoom )
590 if ( rowMaxZoom >= 0 && rowMaxZoom < mCurrentZoom )
594 if ( !mFilterString.isEmpty() )
596 const QString name = sourceModel()->data( sourceModel()->index( source_row, 0, source_parent ), QgsVectorTileBasicRendererListModel::Label ).toString();
597 const QString layer = sourceModel()->data( sourceModel()->index( source_row, 0, source_parent ), QgsVectorTileBasicRendererListModel::Layer ).toString();
598 const QString filter = sourceModel()->data( sourceModel()->index( source_row, 0, source_parent ), QgsVectorTileBasicRendererListModel::Filter ).toString();
599 if ( !name.contains( mFilterString, Qt::CaseInsensitive )
600 && !layer.contains( mFilterString, Qt::CaseInsensitive )
601 && !filter.contains( mFilterString, Qt::CaseInsensitive ) )