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, [
this]( 
bool filter ) {
 
  357    mProxyModel->setFilterVisible( filter );
 
  360  connect( mFilterLineEdit, &QgsFilterLineEdit::textChanged, 
this, [
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.
 
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.
 
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,...