30#include <QAbstractListModel>
31#include <QInputDialog>
37#include "moc_qgsvectortilebasicrendererwidget.cpp"
39using namespace Qt::StringLiterals;
44QgsVectorTileBasicRendererListModel::QgsVectorTileBasicRendererListModel(
QgsVectorTileBasicRenderer *r, QObject *parent, QScreen *screen )
45 : QAbstractListModel( parent )
51int QgsVectorTileBasicRendererListModel::rowCount(
const QModelIndex &parent )
const
53 if ( parent.isValid() )
56 return mRenderer->styles().count();
59int QgsVectorTileBasicRendererListModel::columnCount(
const QModelIndex & )
const
64QVariant QgsVectorTileBasicRendererListModel::data(
const QModelIndex &index,
int role )
const
66 if ( index.row() < 0 || index.row() >= mRenderer->styles().count() )
69 const QList<QgsVectorTileBasicRendererStyle> styles = mRenderer->styles();
77 if ( index.column() == 0 )
79 else if ( index.column() == 1 )
80 return style.
layerName().isEmpty() ? tr(
"(all layers)" ) : style.layerName();
81 else if ( index.column() == 2 )
83 else if ( index.column() == 3 )
85 else if ( index.column() == 4 )
93 if ( index.column() == 0 )
95 else if ( index.column() == 1 )
97 else if ( index.column() == 2 )
99 else if ( index.column() == 3 )
101 else if ( index.column() == 4 )
107 case Qt::DecorationRole:
109 if ( index.column() == 0 && style.
symbol() )
117 case Qt::CheckStateRole:
119 if ( index.column() != 0 )
121 return style.
isEnabled() ? Qt::Checked : Qt::Unchecked;
142QVariant QgsVectorTileBasicRendererListModel::headerData(
int section, Qt::Orientation orientation,
int role )
const
144 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 && section < 5 )
147 lst << tr(
"Label" ) << tr(
"Layer" ) << tr(
"Min. Zoom" ) << tr(
"Max. Zoom" ) << tr(
"Filter" );
154Qt::ItemFlags QgsVectorTileBasicRendererListModel::flags(
const QModelIndex &index )
const
156 if ( !index.isValid() )
157 return Qt::ItemIsDropEnabled;
159 const Qt::ItemFlag checkable = ( index.column() == 0 ? Qt::ItemIsUserCheckable : Qt::NoItemFlags );
161 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | checkable | Qt::ItemIsDragEnabled;
164bool QgsVectorTileBasicRendererListModel::setData(
const QModelIndex &index,
const QVariant &value,
int role )
166 if ( !index.isValid() )
171 if ( role == Qt::CheckStateRole )
173 style.
setEnabled( value.toInt() == Qt::Checked );
174 mRenderer->setStyle( index.row(), style );
175 emit dataChanged( index, index );
179 if ( role == Qt::EditRole )
181 if ( index.column() == 0 )
183 else if ( index.column() == 1 )
185 else if ( index.column() == 2 )
187 else if ( index.column() == 3 )
189 else if ( index.column() == 4 )
192 mRenderer->setStyle( index.row(), style );
193 emit dataChanged( index, index );
200bool QgsVectorTileBasicRendererListModel::removeRows(
int row,
int count,
const QModelIndex &parent )
202 QList<QgsVectorTileBasicRendererStyle> styles = mRenderer->styles();
204 if ( row < 0 || row >= styles.count() )
207 beginRemoveRows( parent, row, row + count - 1 );
209 for (
int i = 0; i < count; i++ )
211 if ( row < styles.count() )
213 styles.removeAt( row );
217 mRenderer->setStyles( styles );
225 beginInsertRows( QModelIndex(), row, row );
227 QList<QgsVectorTileBasicRendererStyle> styles = mRenderer->styles();
228 styles.insert( row, style );
229 mRenderer->setStyles( styles );
234Qt::DropActions QgsVectorTileBasicRendererListModel::supportedDropActions()
const
236 return Qt::MoveAction;
239QStringList QgsVectorTileBasicRendererListModel::mimeTypes()
const
242 types << u
"application/vnd.text.list"_s;
246QMimeData *QgsVectorTileBasicRendererListModel::mimeData(
const QModelIndexList &indexes )
const
248 QMimeData *mimeData =
new QMimeData();
249 QByteArray encodedData;
251 QDataStream stream( &encodedData, QIODevice::WriteOnly );
253 const auto constIndexes = indexes;
254 for (
const QModelIndex &index : constIndexes )
257 if ( !index.isValid() || index.column() != 0 )
263 QDomElement rootElem = doc.createElement( u
"vector_tile_basic_renderer_style_mime"_s );
265 doc.appendChild( rootElem );
267 stream << doc.toString( -1 );
270 mimeData->setData( u
"application/vnd.text.list"_s, encodedData );
274bool QgsVectorTileBasicRendererListModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
int row,
int column,
const QModelIndex &parent )
278 if ( action == Qt::IgnoreAction )
281 if ( !data->hasFormat( u
"application/vnd.text.list"_s ) )
284 if ( parent.column() > 0 )
287 QByteArray encodedData = data->data( u
"application/vnd.text.list"_s );
288 QDataStream stream( &encodedData, QIODevice::ReadOnly );
294 row = rowCount( parent );
297 while ( !stream.atEnd() )
303 if ( !doc.setContent( text ) )
305 const QDomElement rootElem = doc.documentElement();
306 if ( rootElem.tagName() !=
"vector_tile_basic_renderer_style_mime"_L1 )
312 insertStyle( row + rows, style );
324 , mMapCanvas( canvas )
325 , mMessageBar( messageBar )
328 layout()->setContentsMargins( 0, 0, 0, 0 );
330 mFilterLineEdit->setShowClearButton(
true );
331 mFilterLineEdit->setShowSearchIcon(
true );
332 mFilterLineEdit->setPlaceholderText( tr(
"Filter rules" ) );
334 QMenu *menuAddRule =
new QMenu( btnAddRule );
338 btnAddRule->setMenu( menuAddRule );
340 connect( btnEditRule, &QPushButton::clicked,
this, &QgsVectorTileBasicRendererWidget::editStyle );
341 connect( btnRemoveRule, &QAbstractButton::clicked,
this, &QgsVectorTileBasicRendererWidget::removeStyle );
343 connect( viewStyles, &QAbstractItemView::doubleClicked,
this, &QgsVectorTileBasicRendererWidget::editStyleAtIndex );
349 const double tileScale = mVTLayer ? mVTLayer->tileMatrixSet().calculateTileScaleForMap( mMapCanvas->scale(), mapSettings.
destinationCrs(), mapSettings.
visibleExtent(), mapSettings.
outputSize(), mapSettings.
outputDpi() ) : scale;
351 mLabelCurrentZoom->setText( tr(
"Current zoom: %1" ).arg( zoom ) );
353 mProxyModel->setCurrentZoom( zoom );
357 const double tileScale = mVTLayer ? mVTLayer->tileMatrixSet().calculateTileScaleForMap( mMapCanvas->scale(), mapSettings.destinationCrs(), mapSettings.visibleExtent(), mapSettings.outputSize(), mapSettings.outputDpi() ) : mMapCanvas->
scale();
358 mLabelCurrentZoom->setText( tr(
"Current zoom: %1" ).arg( mVTLayer ? mVTLayer->tileMatrixSet().scaleToZoomLevel( tileScale ) :
QgsVectorTileUtils::scaleToZoomLevel( tileScale, 0, 99 ) ) );
361 connect( mCheckVisibleOnly, &QCheckBox::toggled,
this, [
this](
bool filter ) {
362 mProxyModel->setFilterVisible( filter );
365 connect( mFilterLineEdit, &QgsFilterLineEdit::textChanged,
this, [
this](
const QString &text ) {
366 mProxyModel->setFilterString( text );
369 syncToLayer( layer );
372 connect( mBlendModeComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &
QgsPanelWidget::widgetChanged );
375void QgsVectorTileBasicRendererWidget::syncToLayer(
QgsMapLayer *layer )
389 mRenderer = std::make_unique<QgsVectorTileBasicRenderer>();
392 mModel =
new QgsVectorTileBasicRendererListModel( mRenderer.get(), viewStyles, screen() );
393 mProxyModel =
new QgsVectorTileBasicRendererProxyModel( mModel, viewStyles );
394 viewStyles->setModel( mProxyModel );
401 mProxyModel->setCurrentZoom( zoom );
408 mOpacityWidget->setOpacity( mVTLayer->opacity() );
412 mBlendModeComboBox->setBlendMode( mVTLayer->blendMode() );
415QgsVectorTileBasicRendererWidget::~QgsVectorTileBasicRendererWidget() =
default;
417void QgsVectorTileBasicRendererWidget::apply()
419 mVTLayer->setRenderer( mRenderer->clone() );
420 mVTLayer->setBlendMode( mBlendModeComboBox->blendMode() );
421 mVTLayer->setOpacity( mOpacityWidget->opacity() );
445 const int rows = mModel->rowCount();
446 mModel->insertStyle( rows, style );
447 viewStyles->selectionModel()->setCurrentIndex( mProxyModel->mapFromSource( mModel->index( rows, 0 ) ), QItemSelectionModel::ClearAndSelect );
450void QgsVectorTileBasicRendererWidget::editStyle()
452 editStyleAtIndex( viewStyles->selectionModel()->currentIndex() );
455void QgsVectorTileBasicRendererWidget::editStyleAtIndex(
const QModelIndex &proxyIndex )
457 const QModelIndex index = mProxyModel->mapToSource( proxyIndex );
458 if ( index.row() < 0 || index.row() >= mRenderer->styles().count() )
466 std::unique_ptr<QgsSymbol> symbol( style.
symbol()->
clone() );
499 dlg.setContext( context );
500 if ( !dlg.exec() || !symbol )
506 mRenderer->setStyle( index.row(), style );
507 emit widgetChanged();
513 const int index = mProxyModel->mapToSource( viewStyles->selectionModel()->currentIndex() ).row();
521 mRenderer->setStyle( index, style );
522 emit widgetChanged();
525void QgsVectorTileBasicRendererWidget::removeStyle()
527 const QModelIndexList sel = viewStyles->selectionModel()->selectedIndexes();
530 for (
const QModelIndex &proxyIndex : sel )
532 const QModelIndex sourceIndex = mProxyModel->mapToSource( proxyIndex );
533 if ( !res.contains( sourceIndex.row() ) )
534 res << sourceIndex.row();
536 std::sort( res.begin(), res.end() );
538 for (
int i = res.size() - 1; i >= 0; --i )
540 mModel->removeRow( res[i] );
543 viewStyles->selectionModel()->clear();
546QgsVectorTileBasicRendererProxyModel::QgsVectorTileBasicRendererProxyModel( QgsVectorTileBasicRendererListModel *source, QObject *parent )
547 : QSortFilterProxyModel( parent )
549 setSourceModel( source );
550 setDynamicSortFilter(
true );
553void QgsVectorTileBasicRendererProxyModel::setCurrentZoom(
int zoom )
559void QgsVectorTileBasicRendererProxyModel::setFilterVisible(
bool enabled )
561 mFilterVisible = enabled;
565void QgsVectorTileBasicRendererProxyModel::setFilterString(
const QString &
string )
567 mFilterString = string;
571bool QgsVectorTileBasicRendererProxyModel::filterAcceptsRow(
int source_row,
const QModelIndex &source_parent )
const
573 if ( mCurrentZoom >= 0 && mFilterVisible )
575 const int rowMinZoom = sourceModel()->data( sourceModel()->index( source_row, 0, source_parent ), QgsVectorTileBasicRendererListModel::MinZoom ).toInt();
576 const int rowMaxZoom = sourceModel()->data( sourceModel()->index( source_row, 0, source_parent ), QgsVectorTileBasicRendererListModel::MaxZoom ).toInt();
578 if ( rowMinZoom >= 0 && rowMinZoom > mCurrentZoom )
581 if ( rowMaxZoom >= 0 && rowMaxZoom < mCurrentZoom )
585 if ( !mFilterString.isEmpty() )
587 const QString name = sourceModel()->data( sourceModel()->index( source_row, 0, source_parent ), QgsVectorTileBasicRendererListModel::Label ).toString();
588 const QString layer = sourceModel()->data( sourceModel()->index( source_row, 0, source_parent ), QgsVectorTileBasicRendererListModel::Layer ).toString();
589 const QString filter = sourceModel()->data( sourceModel()->index( source_row, 0, source_parent ), QgsVectorTileBasicRendererListModel::Filter ).toString();
590 if ( !name.contains( mFilterString, Qt::CaseInsensitive )
591 && !layer.contains( mFilterString, Qt::CaseInsensitive )
592 && !filter.contains( mFilterString, Qt::CaseInsensitive ) )
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
Single scope for storing variables and functions for use within a QgsExpressionContext.
void setVariable(const QString &name, const QVariant &value, bool isStatic=false)
Convenience method for setting a variable in the context scope by name name and value.
Map canvas is a class for displaying all GIS data types on a canvas.
void scaleChanged(double scale)
Emitted when the scale of the map changes.
Base class for all map layer types.
Contains configuration for rendering maps.
double scale() const
Returns the calculated map scale.
QSize outputSize() const
Returns the size of the resulting map image, in pixels.
QgsRectangle visibleExtent() const
Returns the actual extent derived from requested extent that takes output image size into account.
double outputDpi() const
Returns the DPI (dots per inch) used for conversion between real world units (e.g.
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system for the map render.
A bar for displaying non-blocking messages to the user.
static bool layerIsContainedInGroupLayer(QgsProject *project, QgsMapLayer *layer)
Returns true if the specified layer is a child layer from any QgsGroupLayer in the given project.
static QgsProject * instance()
Returns the QgsProject singleton instance.
A container for the context for various read/write operations on objects.
Stores properties relating to a screen.
static QgsStyle * defaultStyle(bool initialize=true)
Returns the default application-wide style.
static QIcon symbolPreviewIcon(const QgsSymbol *symbol, QSize size, int padding=0, QgsLegendPatchShape *shape=nullptr, const QgsScreenProperties &screen=QgsScreenProperties())
Returns an icon preview for a color ramp.
A dialog that can be used to select and build a symbol.
Contains settings which reflect the context in which a symbol (or renderer) widget is shown,...
QList< QgsExpressionContextScope > additionalExpressionContextScopes() const
Returns the list of additional expression context scopes to show as available within the layer.
void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
void setAdditionalExpressionContextScopes(const QList< QgsExpressionContextScope > &scopes)
Sets a list of additional expression context scopes to show as available within the layer.
void setMessageBar(QgsMessageBar *bar)
Sets the message bar associated with the widget.
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
static QgsSymbol * defaultSymbol(Qgis::GeometryType geomType)
Returns a new default symbol for the specified geometry type.
Represents a vector layer which manages a vector based dataset.
Definition of map rendering of a subset of vector tile data.
void setEnabled(bool enabled)
Sets whether this style is enabled (used for rendering).
void setMinZoomLevel(int minZoom)
Sets minimum zoom level index (negative number means no limit).
void setLayerName(const QString &name)
Sets name of the sub-layer to render (empty layer means that all layers match).
QgsSymbol * symbol() const
Returns symbol for rendering.
QString filterExpression() const
Returns filter expression (empty filter means that all features match).
QString styleName() const
Returns human readable name of this style.
void setFilterExpression(const QString &expr)
Sets filter expression (empty filter means that all features match).
void setSymbol(QgsSymbol *sym)
Sets symbol for rendering. Takes ownership of the symbol.
void writeXml(QDomElement &elem, const QgsReadWriteContext &context) const
Writes object content to given DOM element.
void setStyleName(const QString &name)
Sets human readable name of this style.
bool isEnabled() const
Returns whether this style is enabled (used for rendering).
void setMaxZoomLevel(int maxZoom)
Sets maximum zoom level index (negative number means no limit).
int minZoomLevel() const
Returns the minimum zoom level index (negative number means no limit).
int maxZoomLevel() const
Returns the maximum zoom level index (negative number means no limit).
QString layerName() const
Returns name of the sub-layer to render (empty layer means that all layers match).
void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Reads object content from given DOM element.
The default vector tile renderer implementation.
Implements a map layer that is dedicated to rendering of vector tiles.
QgsVectorTileRenderer * renderer() const
Returns currently assigned renderer.
virtual QString type() const =0
Returns unique type name of the renderer implementation.
virtual QgsVectorTileRenderer * clone() const =0
Returns a clone of the renderer.
static double scaleToZoom(double mapScale, double z0Scale=559082264.0287178)
Finds zoom level given map scale denominator.
static int scaleToZoomLevel(double mapScale, int sourceMinZoom, int sourceMaxZoom, double z0Scale=559082264.0287178)
Finds the best fitting zoom level given a map scale denominator and allowed zoom level range.
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window's toolbar icons.
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly,...