17#include "moc_qgsvectortilebasicrendererwidget.cpp"
29#include <QAbstractListModel>
30#include <QInputDialog>
39QgsVectorTileBasicRendererListModel::QgsVectorTileBasicRendererListModel(
QgsVectorTileBasicRenderer *r, QObject *parent, QScreen *screen )
40 : QAbstractListModel( parent )
46int QgsVectorTileBasicRendererListModel::rowCount(
const QModelIndex &parent )
const
48 if ( parent.isValid() )
51 return mRenderer->styles().count();
54int QgsVectorTileBasicRendererListModel::columnCount(
const QModelIndex & )
const
59QVariant QgsVectorTileBasicRendererListModel::data(
const QModelIndex &index,
int role )
const
61 if ( index.row() < 0 || index.row() >= mRenderer->styles().count() )
64 const QList<QgsVectorTileBasicRendererStyle> styles = mRenderer->styles();
72 if ( index.column() == 0 )
74 else if ( index.column() == 1 )
75 return style.
layerName().isEmpty() ? tr(
"(all layers)" ) : style.layerName();
76 else if ( index.column() == 2 )
78 else if ( index.column() == 3 )
80 else if ( index.column() == 4 )
81 return style.
filterExpression().isEmpty() ? tr(
"(no filter)" ) : style.filterExpression();
88 if ( index.column() == 0 )
90 else if ( index.column() == 1 )
92 else if ( index.column() == 2 )
94 else if ( index.column() == 3 )
96 else if ( index.column() == 4 )
102 case Qt::DecorationRole:
104 if ( index.column() == 0 && style.
symbol() )
112 case Qt::CheckStateRole:
114 if ( index.column() != 0 )
116 return style.
isEnabled() ? Qt::Checked : Qt::Unchecked;
137QVariant QgsVectorTileBasicRendererListModel::headerData(
int section, Qt::Orientation orientation,
int role )
const
139 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 && section < 5 )
142 lst << tr(
"Label" ) << tr(
"Layer" ) << tr(
"Min. Zoom" ) << tr(
"Max. Zoom" ) << tr(
"Filter" );
149Qt::ItemFlags QgsVectorTileBasicRendererListModel::flags(
const QModelIndex &index )
const
151 if ( !index.isValid() )
152 return Qt::ItemIsDropEnabled;
154 const Qt::ItemFlag checkable = ( index.column() == 0 ? Qt::ItemIsUserCheckable : Qt::NoItemFlags );
156 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | checkable | Qt::ItemIsDragEnabled;
159bool QgsVectorTileBasicRendererListModel::setData(
const QModelIndex &index,
const QVariant &value,
int role )
161 if ( !index.isValid() )
166 if ( role == Qt::CheckStateRole )
168 style.
setEnabled( value.toInt() == Qt::Checked );
169 mRenderer->setStyle( index.row(), style );
170 emit dataChanged( index, index );
174 if ( role == Qt::EditRole )
176 if ( index.column() == 0 )
178 else if ( index.column() == 1 )
180 else if ( index.column() == 2 )
182 else if ( index.column() == 3 )
184 else if ( index.column() == 4 )
187 mRenderer->setStyle( index.row(), style );
188 emit dataChanged( index, index );
195bool QgsVectorTileBasicRendererListModel::removeRows(
int row,
int count,
const QModelIndex &parent )
197 QList<QgsVectorTileBasicRendererStyle> styles = mRenderer->styles();
199 if ( row < 0 || row >= styles.count() )
202 beginRemoveRows( parent, row, row + count - 1 );
204 for (
int i = 0; i < count; i++ )
206 if ( row < styles.count() )
208 styles.removeAt( row );
212 mRenderer->setStyles( styles );
220 beginInsertRows( QModelIndex(), row, row );
222 QList<QgsVectorTileBasicRendererStyle> styles = mRenderer->styles();
223 styles.insert( row, style );
224 mRenderer->setStyles( styles );
229Qt::DropActions QgsVectorTileBasicRendererListModel::supportedDropActions()
const
231 return Qt::MoveAction;
234QStringList QgsVectorTileBasicRendererListModel::mimeTypes()
const
237 types << QStringLiteral(
"application/vnd.text.list" );
241QMimeData *QgsVectorTileBasicRendererListModel::mimeData(
const QModelIndexList &indexes )
const
243 QMimeData *mimeData =
new QMimeData();
244 QByteArray encodedData;
246 QDataStream stream( &encodedData, QIODevice::WriteOnly );
248 const auto constIndexes = indexes;
249 for (
const QModelIndex &index : constIndexes )
252 if ( !index.isValid() || index.column() != 0 )
258 QDomElement rootElem = doc.createElement( QStringLiteral(
"vector_tile_basic_renderer_style_mime" ) );
260 doc.appendChild( rootElem );
262 stream << doc.toString( -1 );
265 mimeData->setData( QStringLiteral(
"application/vnd.text.list" ), encodedData );
269bool QgsVectorTileBasicRendererListModel::dropMimeData(
const QMimeData *data, Qt::DropAction action,
int row,
int column,
const QModelIndex &parent )
273 if ( action == Qt::IgnoreAction )
276 if ( !data->hasFormat( QStringLiteral(
"application/vnd.text.list" ) ) )
279 if ( parent.column() > 0 )
282 QByteArray encodedData = data->data( QStringLiteral(
"application/vnd.text.list" ) );
283 QDataStream stream( &encodedData, QIODevice::ReadOnly );
289 row = rowCount( parent );
292 while ( !stream.atEnd() )
298 if ( !doc.setContent( text ) )
300 const QDomElement rootElem = doc.documentElement();
301 if ( rootElem.tagName() != QLatin1String(
"vector_tile_basic_renderer_style_mime" ) )
307 insertStyle( row + rows, style );
319 , mMapCanvas( canvas )
320 , mMessageBar( messageBar )
323 layout()->setContentsMargins( 0, 0, 0, 0 );
325 mFilterLineEdit->setShowClearButton(
true );
326 mFilterLineEdit->setShowSearchIcon(
true );
327 mFilterLineEdit->setPlaceholderText( tr(
"Filter rules" ) );
329 QMenu *menuAddRule =
new QMenu( btnAddRule );
333 btnAddRule->setMenu( menuAddRule );
335 connect( btnEditRule, &QPushButton::clicked,
this, &QgsVectorTileBasicRendererWidget::editStyle );
336 connect( btnRemoveRule, &QAbstractButton::clicked,
this, &QgsVectorTileBasicRendererWidget::removeStyle );
338 connect( viewStyles, &QAbstractItemView::doubleClicked,
this, &QgsVectorTileBasicRendererWidget::editStyleAtIndex );
344 const double tileScale = mVTLayer ? mVTLayer->tileMatrixSet().calculateTileScaleForMap( mMapCanvas->scale(), mapSettings.
destinationCrs(), mapSettings.
visibleExtent(), mapSettings.
outputSize(), mapSettings.
outputDpi() ) : scale;
346 mLabelCurrentZoom->setText( tr(
"Current zoom: %1" ).arg( zoom ) );
348 mProxyModel->setCurrentZoom( zoom );
352 const double tileScale = mVTLayer ? mVTLayer->tileMatrixSet().calculateTileScaleForMap( mMapCanvas->scale(), mapSettings.destinationCrs(), mapSettings.visibleExtent(), mapSettings.outputSize(), mapSettings.outputDpi() ) : mMapCanvas->scale();
353 mLabelCurrentZoom->setText( tr(
"Current zoom: %1" ).arg( mVTLayer ? mVTLayer->tileMatrixSet().scaleToZoomLevel( tileScale ) :
QgsVectorTileUtils::scaleToZoomLevel( tileScale, 0, 99 ) ) );
356 connect( mCheckVisibleOnly, &QCheckBox::toggled,
this, [=](
bool filter ) {
357 mProxyModel->setFilterVisible( filter );
360 connect( mFilterLineEdit, &QgsFilterLineEdit::textChanged,
this, [=](
const QString &text ) {
361 mProxyModel->setFilterString( text );
364 syncToLayer( layer );
367 connect( mBlendModeComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &
QgsPanelWidget::widgetChanged );
370void QgsVectorTileBasicRendererWidget::syncToLayer(
QgsMapLayer *layer )
387 mModel =
new QgsVectorTileBasicRendererListModel( mRenderer.get(), viewStyles, screen() );
388 mProxyModel =
new QgsVectorTileBasicRendererProxyModel( mModel, viewStyles );
389 viewStyles->setModel( mProxyModel );
396 mProxyModel->setCurrentZoom( zoom );
403 mOpacityWidget->setOpacity( mVTLayer->opacity() );
407 mBlendModeComboBox->setBlendMode( mVTLayer->blendMode() );
410QgsVectorTileBasicRendererWidget::~QgsVectorTileBasicRendererWidget() =
default;
412void QgsVectorTileBasicRendererWidget::apply()
414 mVTLayer->setRenderer( mRenderer->clone() );
415 mVTLayer->setBlendMode( mBlendModeComboBox->blendMode() );
416 mVTLayer->setOpacity( mOpacityWidget->opacity() );
440 const int rows = mModel->rowCount();
441 mModel->insertStyle( rows, style );
442 viewStyles->selectionModel()->setCurrentIndex( mProxyModel->mapFromSource( mModel->index( rows, 0 ) ), QItemSelectionModel::ClearAndSelect );
445void QgsVectorTileBasicRendererWidget::editStyle()
447 editStyleAtIndex( viewStyles->selectionModel()->currentIndex() );
450void QgsVectorTileBasicRendererWidget::editStyleAtIndex(
const QModelIndex &proxyIndex )
452 const QModelIndex index = mProxyModel->mapToSource( proxyIndex );
453 if ( index.row() < 0 || index.row() >= mRenderer->styles().count() )
461 std::unique_ptr<QgsSymbol> symbol( style.
symbol()->
clone() );
475 tileScope.
setVariable(
"vector_tile_zoom", mVTLayer ? mVTLayer->tileMatrixSet().scaleToZoom( mMapCanvas->scale() ) :
QgsVectorTileUtils::scaleToZoom( mMapCanvas->scale() ), true );
494 dlg.setContext( context );
495 if ( !dlg.exec() || !symbol )
501 mRenderer->setStyle( index.row(), style );
502 emit widgetChanged();
508 const int index = mProxyModel->mapToSource( viewStyles->selectionModel()->currentIndex() ).row();
516 mRenderer->setStyle( index, style );
517 emit widgetChanged();
520void QgsVectorTileBasicRendererWidget::removeStyle()
522 const QModelIndexList sel = viewStyles->selectionModel()->selectedIndexes();
525 for (
const QModelIndex &proxyIndex : sel )
527 const QModelIndex sourceIndex = mProxyModel->mapToSource( proxyIndex );
528 if ( !res.contains( sourceIndex.row() ) )
529 res << sourceIndex.row();
531 std::sort( res.begin(), res.end() );
533 for (
int i = res.size() - 1; i >= 0; --i )
535 mModel->removeRow( res[i] );
538 viewStyles->selectionModel()->clear();
541QgsVectorTileBasicRendererProxyModel::QgsVectorTileBasicRendererProxyModel( QgsVectorTileBasicRendererListModel *source, QObject *parent )
542 : QSortFilterProxyModel( parent )
544 setSourceModel( source );
545 setDynamicSortFilter(
true );
548void QgsVectorTileBasicRendererProxyModel::setCurrentZoom(
int zoom )
554void QgsVectorTileBasicRendererProxyModel::setFilterVisible(
bool enabled )
556 mFilterVisible = enabled;
560void QgsVectorTileBasicRendererProxyModel::setFilterString(
const QString &
string )
562 mFilterString = string;
566bool QgsVectorTileBasicRendererProxyModel::filterAcceptsRow(
int source_row,
const QModelIndex &source_parent )
const
568 if ( mCurrentZoom >= 0 && mFilterVisible )
570 const int rowMinZoom = sourceModel()->data( sourceModel()->index( source_row, 0, source_parent ), QgsVectorTileBasicRendererListModel::MinZoom ).toInt();
571 const int rowMaxZoom = sourceModel()->data( sourceModel()->index( source_row, 0, source_parent ), QgsVectorTileBasicRendererListModel::MaxZoom ).toInt();
573 if ( rowMinZoom >= 0 && rowMinZoom > mCurrentZoom )
576 if ( rowMaxZoom >= 0 && rowMaxZoom < mCurrentZoom )
580 if ( !mFilterString.isEmpty() )
582 const QString name = sourceModel()->data( sourceModel()->index( source_row, 0, source_parent ), QgsVectorTileBasicRendererListModel::Label ).toString();
583 const QString layer = sourceModel()->data( sourceModel()->index( source_row, 0, source_parent ), QgsVectorTileBasicRendererListModel::Layer ).toString();
584 const QString filter = sourceModel()->data( sourceModel()->index( source_row, 0, source_parent ), QgsVectorTileBasicRendererListModel::Filter ).toString();
585 if ( !name.contains( mFilterString, Qt::CaseInsensitive )
586 && !layer.contains( mFilterString, Qt::CaseInsensitive )
587 && !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.
The QgsMapSettings class contains configuration for rendering of the map.
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.
The class is used as a container of context for various read/write operations on other 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 data sets.
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.
Random utility functions for working with vector tiles.
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,...