Skip to content
Permalink
Browse files

gui for dynamic SVGs

  • Loading branch information
3nids committed Jan 7, 2021
1 parent 17500a7 commit 9161a8c8b53c8df3a6b930d0e35c7d25bef7c1fd
@@ -11,6 +11,8 @@





class QgsSvgSelectorListModel : QAbstractListModel
{
%Docstring
@@ -80,6 +82,13 @@ class QgsSvgSelectorWidget : QWidget
QgsSvgSelectorWidget( QWidget *parent /TransferThis/ = 0 );
%Docstring
Constructor for QgsSvgSelectorWidget
%End

void initParametersModel( const QgsExpressionContextGenerator *generator, QgsVectorLayer *layer );
%Docstring
Initialize the parameters model so the context and the layer are referenced.

.. versionadded:: 3.18
%End

QString currentSvgPath() const;
@@ -89,16 +98,38 @@ Constructor for QgsSvgSelectorWidget
Returns the source line edit

.. versionadded:: 3.16
%End

void setAllowParameters( bool allow );
%Docstring
Defines if the group box to fill parameters is visible

.. versionadded:: 3.18
%End

bool allowParamerters() const;
%Docstring
Returns if the group box to fill parameters is visible

.. versionadded:: 3.18
%End

public slots:
void setSvgPath( const QString &svgPath );
%Docstring
Accepts absolute paths
%End

void setSvgParameters( const QMap<QString, QgsProperty> &parameters );
%Docstring
Sets the dynamic parameters

.. versionadded:: 3.18
%End

signals:
void svgSelected( const QString &path );
void svgParametersChanged( const QMap<QString, QgsProperty> &parameters );

protected:
void populateList();
@@ -453,6 +453,10 @@ Creates a new QgsSvgMarkerSymbolLayerWidget.
void setSvgPath( const QString &name );
%Docstring
Sets the SVG path
%End
void setSvgParameters( const QMap<QString, QgsProperty> &parameters );
%Docstring
Sets the dynamic SVG parameters
%End


@@ -24,6 +24,9 @@
#include "qgssymbollayerutils.h"
#include "qgssettings.h"
#include "qgsgui.h"
#include "qgsfieldexpressionwidget.h"
#include "qgssymbollayerwidget.h"
#include "qgsvectorlayer.h"

#include <QAbstractListModel>
#include <QCheckBox>
@@ -396,10 +399,33 @@ QgsSvgSelectorWidget::QgsSvgSelectorWidget( QWidget *parent )
mGroupsTreeView->setHeaderHidden( true );
populateList();

connect( mImagesListView->selectionModel(), &QItemSelectionModel::currentChanged,
this, &QgsSvgSelectorWidget::svgSelectionChanged );
connect( mGroupsTreeView->selectionModel(), &QItemSelectionModel::currentChanged,
this, &QgsSvgSelectorWidget::populateIcons );
mParametersModel = new QgsSvgParametersModel( this );
mParametersTreeView->setModel( mParametersModel );
mParametersGroupBox->setVisible( mAllowParameters );

mParametersTreeView->setItemDelegateForColumn( static_cast<int>( QgsSvgParametersModel::Column::ExpressionColumn ), new QgsSvgParameterValueDelegate( this ) );
mParametersTreeView->header()->setSectionResizeMode( QHeaderView::ResizeToContents );
mParametersTreeView->header()->setStretchLastSection( true );
mParametersTreeView->setSelectionBehavior( QAbstractItemView::SelectRows );
mParametersTreeView->setSelectionMode( QAbstractItemView::SingleSelection );
mParametersTreeView->setEditTriggers( QAbstractItemView::DoubleClicked );

connect( mParametersModel, &QgsSvgParametersModel::parametersChanged, this, &QgsSvgSelectorWidget::svgParametersChanged );
connect( mImagesListView->selectionModel(), &QItemSelectionModel::currentChanged, this, &QgsSvgSelectorWidget::svgSelectionChanged );
connect( mGroupsTreeView->selectionModel(), &QItemSelectionModel::currentChanged, this, &QgsSvgSelectorWidget::populateIcons );
connect( mAddParameterButton, &QToolButton::clicked, mParametersModel, &QgsSvgParametersModel::addParameter );
connect( mRemoveParameterButton, &QToolButton::clicked, this, [ = ]()
{
const QModelIndexList selectedRows = mParametersTreeView->selectionModel()->selectedRows();
if ( selectedRows.count() > 0 )
mParametersModel->removeParameter( selectedRows.at( 0 ) );
} );
}

void QgsSvgSelectorWidget::initParametersModel( const QgsExpressionContextGenerator *generator, QgsVectorLayer *layer )
{
mParametersModel->setExpressionContextGenerator( generator );
mParametersModel->setLayer( layer );
}

void QgsSvgSelectorWidget::setSvgPath( const QString &svgPath )
@@ -425,11 +451,25 @@ void QgsSvgSelectorWidget::setSvgPath( const QString &svgPath )
mImagesListView->selectionModel()->blockSignals( false );
}

void QgsSvgSelectorWidget::setSvgParameters( const QMap<QString, QgsProperty> &parameters )
{
mParametersModel->setParameters( parameters );
}

QString QgsSvgSelectorWidget::currentSvgPath() const
{
return mCurrentSvgPath;
}

void QgsSvgSelectorWidget::setAllowParameters( bool allow )
{
if ( mAllowParameters == allow )
return;

mAllowParameters = allow;
mParametersGroupBox->setVisible( allow );
}

void QgsSvgSelectorWidget::updateCurrentSvgPath( const QString &svgPath )
{
mCurrentSvgPath = svgPath;
@@ -508,3 +548,189 @@ QgsSvgSelectorDialog::QgsSvgSelectorDialog( QWidget *parent, Qt::WindowFlags fl,
setLayout( mLayout );
}



QgsSvgParametersModel::QgsSvgParametersModel( QObject *parent )
: QAbstractTableModel( parent )
{
connect( this, &QAbstractTableModel::rowsInserted, this, [ = ]() {emit parametersChanged( parameters() );} );
connect( this, &QAbstractTableModel::rowsRemoved, this, [ = ]() {emit parametersChanged( parameters() );} );
connect( this, &QAbstractTableModel::dataChanged, this, [ = ]() {emit parametersChanged( parameters() );} );
}

void QgsSvgParametersModel::setParameters( const QMap<QString, QgsProperty> &parameters )
{
beginResetModel();
mParameters.clear();
QMap<QString, QgsProperty>::const_iterator paramIt = parameters.constBegin();
for ( ; paramIt != parameters.constEnd(); ++paramIt )
{
mParameters << Parameter( paramIt.key(), paramIt.value() );
}
endResetModel();
}

QMap<QString, QgsProperty> QgsSvgParametersModel::parameters() const
{
QMap<QString, QgsProperty> params;
for ( const Parameter &param : qgis::as_const( mParameters ) )
{
if ( !param.name.isEmpty() )
params.insert( param.name, param.property );
}
return params;
}

void QgsSvgParametersModel::removeParameter( const QModelIndex &index )
{
if ( !index.isValid() )
return;

beginRemoveRows( QModelIndex(), index.row(), index.row() );
mParameters.removeAt( index.row() );
endRemoveRows();
}

void QgsSvgParametersModel::setLayer( QgsVectorLayer *layer )
{
mLayer = layer;
}

void QgsSvgParametersModel::setExpressionContextGenerator( const QgsExpressionContextGenerator *generator )
{
mExpressionContextGenerator = generator;
}

int QgsSvgParametersModel::rowCount( const QModelIndex &parent ) const
{
Q_UNUSED( parent )
return mParameters.count();
}

int QgsSvgParametersModel::columnCount( const QModelIndex &parent ) const
{
Q_UNUSED( parent )
return 2;
}

QVariant QgsSvgParametersModel::data( const QModelIndex &index, int role ) const
{
QgsSvgParametersModel::Column col = static_cast<QgsSvgParametersModel::Column>( index.column() );
if ( role == Qt::DisplayRole )
{
switch ( col )
{
case QgsSvgParametersModel::Column::NameColumn:
return mParameters.at( index.row() ).name;
case QgsSvgParametersModel::Column::ExpressionColumn:
return mParameters.at( index.row() ).property.expressionString();
}
}

return QVariant();
}

bool QgsSvgParametersModel::setData( const QModelIndex &index, const QVariant &value, int role )
{
if ( !index.isValid() || role != Qt::EditRole )
return false;

QgsSvgParametersModel::Column col = static_cast<QgsSvgParametersModel::Column>( index.column() );
switch ( col )
{
case QgsSvgParametersModel::Column::NameColumn:
{
QString oldName = mParameters.at( index.row() ).name;
QString newName = value.toString();
for ( const Parameter &param : qgis::as_const( mParameters ) )
{
if ( param.name == newName && param.name != oldName )
{
// names must be unique!
return false;
}
}
mParameters[index.row()].name = newName;
emit dataChanged( index, index );
return true;
}

case QgsSvgParametersModel::Column::ExpressionColumn:
mParameters[index.row()].property = QgsProperty::fromExpression( value.toString() );
emit dataChanged( index, index );
return true;
}

return false;
}

QVariant QgsSvgParametersModel::headerData( int section, Qt::Orientation orientation, int role ) const
{
if ( role == Qt::DisplayRole && orientation == Qt::Horizontal )
{
QgsSvgParametersModel::Column col = static_cast<QgsSvgParametersModel::Column>( section );
switch ( col )
{
case QgsSvgParametersModel::Column::NameColumn:
return tr( "Name" );
case QgsSvgParametersModel::Column::ExpressionColumn:
return tr( "Expression" );
}
}

return QVariant();
}

void QgsSvgParametersModel::addParameter()
{
int c = rowCount( QModelIndex() );
beginInsertRows( QModelIndex(), c, c );
int i = 1;
QStringList currentNames;
std::transform( mParameters.begin(), mParameters.end(), std::back_inserter( currentNames ), []( const Parameter & parameter ) {return parameter.name;} );
while ( currentNames.contains( QStringLiteral( "param%1" ).arg( i ) ) )
i++;
mParameters.append( Parameter( QStringLiteral( "param%1" ).arg( i ), QgsProperty() ) );
endResetModel();
}


Qt::ItemFlags QgsSvgParametersModel::flags( const QModelIndex &index ) const
{
Q_UNUSED( index )
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
}


QWidget *QgsSvgParameterValueDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const
{
Q_UNUSED( option )
QgsFieldExpressionWidget *w = new QgsFieldExpressionWidget( parent );
const QgsSvgParametersModel *model = qobject_cast<const QgsSvgParametersModel *>( index.model() );
w->registerExpressionContextGenerator( model->expressionContextGenerator() );
w->setLayer( model->layer() );
return w;
}

void QgsSvgParameterValueDelegate::setEditorData( QWidget *editor, const QModelIndex &index ) const
{
QgsFieldExpressionWidget *w = qobject_cast<QgsFieldExpressionWidget *>( editor );
if ( !w )
return;

w->setExpression( index.model()->data( index ).toString() );
}

void QgsSvgParameterValueDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
{
QgsFieldExpressionWidget *w = qobject_cast<QgsFieldExpressionWidget *>( editor );
if ( !w )
return;
model->setData( index, w->currentField() );
}

void QgsSvgParameterValueDelegate::updateEditorGeometry( QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index ) const
{
Q_UNUSED( index )
editor->setGeometry( option.rect );
}

0 comments on commit 9161a8c

Please sign in to comment.
You can’t perform that action at this time.