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 ) )