Skip to content
Permalink
Browse files

[FEATURE][processing] New parameter types for layouts and layout items

Allows processing algorithms which operate on a specific layout
and layout item selection
  • Loading branch information
nyalldawson committed Mar 11, 2019
1 parent f9fb408 commit 021d1ef237065dd40c80b9b5044406f6319b18e0
@@ -79,6 +79,7 @@
PARAMETER_CRS = 'crs'
PARAMETER_MULTIPLE = 'multilayer'
PARAMETER_BAND = 'band'
PARAMETER_LAYOUTITEM = 'layoutitem'
PARAMETER_MAP_LAYER = 'Map Layer'
PARAMETER_RANGE = 'range'
PARAMETER_ENUM = 'enum'
@@ -64,6 +64,8 @@
QgsProcessingParameterField,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterBand,
QgsProcessingParameterLayout,
QgsProcessingParameterLayoutItem,
QgsProcessingDestinationParameter,
QgsProcessingParameterFeatureSink,
QgsProcessingParameterFileDestination,
@@ -180,6 +182,20 @@ def setupUi(self):
self.parentCombo.setCurrentIndex(idx)
idx += 1
self.verticalLayout.addWidget(self.parentCombo)
elif self.paramType == parameters.PARAMETER_LAYOUTITEM or \
isinstance(self.param, QgsProcessingParameterLayoutItem):
self.verticalLayout.addWidget(QLabel(self.tr('Parent layout')))
self.parentCombo = QComboBox()
idx = 0
for param in list(self.alg.parameterComponents().values()):
definition = self.alg.parameterDefinition(param.parameterName())
if isinstance(definition, (QgsProcessingParameterLayout)):
self.parentCombo.addItem(definition.description(), definition.name())
if self.param is not None:
if self.param.parentLayoutParameterName() == definition.name():
self.parentCombo.setCurrentIndex(idx)
idx += 1
self.verticalLayout.addWidget(self.parentCombo)
elif (self.paramType in (
parameters.PARAMETER_VECTOR, parameters.PARAMETER_TABLE) or
isinstance(self.param, (QgsProcessingParameterFeatureSource, QgsProcessingParameterVectorLayer))):
@@ -405,6 +421,14 @@ def accept(self):
return
parent = self.parentCombo.currentData()
self.param = QgsProcessingParameterBand(name, description, None, parent)
elif (self.paramType == parameters.PARAMETER_LAYOUTITEM or
isinstance(self.param, QgsProcessingParameterLayoutItem)):
if self.parentCombo.currentIndex() < 0:
QMessageBox.warning(self, self.tr('Unable to define parameter'),
self.tr('Wrong or missing parameter values'))
return
parent = self.parentCombo.currentData()
self.param = QgsProcessingParameterLayoutItem(name, description, None, parent)
elif (self.paramType == parameters.PARAMETER_MAP_LAYER or
isinstance(self.param, QgsProcessingParameterMapLayer)):
self.param = QgsProcessingParameterMapLayer(
@@ -27,12 +27,14 @@ QgsLayoutItemComboBox::QgsLayoutItemComboBox( QWidget *parent, QgsLayout *layout

void QgsLayoutItemComboBox::setCurrentLayout( QgsLayout *layout )
{
const bool prevAllowEmpty = mProxyModel && mProxyModel->allowEmptyItem();
mProxyModel = qgis::make_unique< QgsLayoutProxyModel >( layout, this );
connect( mProxyModel.get(), &QAbstractItemModel::rowsInserted, this, &QgsLayoutItemComboBox::rowsChanged );
connect( mProxyModel.get(), &QAbstractItemModel::rowsRemoved, this, &QgsLayoutItemComboBox::rowsChanged );
setModel( mProxyModel.get() );
setModelColumn( QgsLayoutModel::ItemId );
mProxyModel->sort( 0, Qt::AscendingOrder );
mProxyModel->setAllowEmptyItem( prevAllowEmpty );
}

QgsLayout *QgsLayoutItemComboBox::currentLayout()
@@ -55,7 +57,7 @@ void QgsLayoutItemComboBox::setItem( const QgsLayoutItem *item )
return;
}
}
setCurrentIndex( mProxyModel->allowEmptyItem() ? 0 : -1 );
setCurrentIndex( mProxyModel->allowEmptyItem() ? mProxyModel->rowCount() - 1 : -1 );
}

QgsLayoutItem *QgsLayoutItemComboBox::currentItem() const
@@ -38,6 +38,8 @@ QgsProcessingGuiRegistry::QgsProcessingGuiRegistry()
addParameterWidgetFactory( new QgsProcessingFileWidgetWrapper() );
addParameterWidgetFactory( new QgsProcessingExpressionWidgetWrapper() );
addParameterWidgetFactory( new QgsProcessingEnumWidgetWrapper() );
addParameterWidgetFactory( new QgsProcessingLayoutWidgetWrapper() );
addParameterWidgetFactory( new QgsProcessingLayoutItemWidgetWrapper() );
}

QgsProcessingGuiRegistry::~QgsProcessingGuiRegistry()
@@ -30,6 +30,11 @@
#include "qgsexpressionlineedit.h"
#include "qgsfieldexpressionwidget.h"
#include "qgsprocessingmultipleselectiondialog.h"
#include "qgslayoutmanager.h"
#include "qgsproject.h"
#include "qgslayoutcombobox.h"
#include "qgslayoutitemcombobox.h"
#include "qgsprintlayout.h"
#include <QLabel>
#include <QHBoxLayout>
#include <QCheckBox>
@@ -1735,5 +1740,286 @@ QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingEnumWidgetWrapper::cre



//
// QgsProcessingLayoutWidgetWrapper
//

QgsProcessingLayoutWidgetWrapper::QgsProcessingLayoutWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
: QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
{

}

QWidget *QgsProcessingLayoutWidgetWrapper::createWidget()
{
const QgsProcessingParameterLayout *layoutParam = dynamic_cast< const QgsProcessingParameterLayout *>( parameterDefinition() );
switch ( type() )
{
case QgsProcessingGui::Standard:
case QgsProcessingGui::Batch:
{
// combobox only for use outside modeler!
mComboBox = new QgsLayoutComboBox( nullptr, widgetContext().project() ? widgetContext().project()->layoutManager() : nullptr );
if ( layoutParam->flags() & QgsProcessingParameterDefinition::FlagOptional )
mComboBox->setAllowEmptyLayout( true );
mComboBox->setFilters( QgsLayoutManagerProxyModel::FilterPrintLayouts );

mComboBox->setToolTip( parameterDefinition()->toolTip() );
connect( mComboBox, &QgsLayoutComboBox::layoutChanged, this, [ = ]( QgsMasterLayoutInterface * )
{
emit widgetValueHasChanged( this );
} );
return mComboBox;
}

case QgsProcessingGui::Modeler:
{
mLineEdit = new QLineEdit();
mLineEdit->setToolTip( tr( "Name of an existing print layout" ) );
connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]( const QString & )
{
emit widgetValueHasChanged( this );
} );
return mLineEdit;
}
}
return nullptr;
}

void QgsProcessingLayoutWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
{
if ( mComboBox )
{
if ( !value.isValid() )
mComboBox->setCurrentLayout( nullptr );
else
{
if ( QgsPrintLayout *l = QgsProcessingParameters::parameterAsLayout( parameterDefinition(), value, context ) )
mComboBox->setCurrentLayout( l );
else
mComboBox->setCurrentLayout( nullptr );
}
}
else if ( mLineEdit )
{
const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
mLineEdit->setText( v );
}
}

QVariant QgsProcessingLayoutWidgetWrapper::widgetValue() const
{
if ( mComboBox )
{
const QgsMasterLayoutInterface *l = mComboBox->currentLayout();
return l ? l->name() : QVariant();
}
else if ( mLineEdit )
return mLineEdit->text().isEmpty() ? QVariant() : mLineEdit->text();
else
return QVariant();
}

QStringList QgsProcessingLayoutWidgetWrapper::compatibleParameterTypes() const
{
return QStringList()
<< QgsProcessingParameterLayout::typeName()
<< QgsProcessingParameterString::typeName();
}

QStringList QgsProcessingLayoutWidgetWrapper::compatibleOutputTypes() const
{
return QStringList()
<< QgsProcessingOutputString::typeName();
}

QList<int> QgsProcessingLayoutWidgetWrapper::compatibleDataTypes() const
{
return QList<int>();
}

QString QgsProcessingLayoutWidgetWrapper::modelerExpressionFormatString() const
{
return tr( "string representing the name of an existing print layout" );
}

QString QgsProcessingLayoutWidgetWrapper::parameterType() const
{
return QgsProcessingParameterLayout::typeName();
}

QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingLayoutWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
{
return new QgsProcessingLayoutWidgetWrapper( parameter, type );
}




//
// QgsProcessingLayoutItemWidgetWrapper
//

QgsProcessingLayoutItemWidgetWrapper::QgsProcessingLayoutItemWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
: QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
{

}

QWidget *QgsProcessingLayoutItemWidgetWrapper::createWidget()
{
const QgsProcessingParameterLayoutItem *layoutParam = dynamic_cast< const QgsProcessingParameterLayoutItem *>( parameterDefinition() );
switch ( type() )
{
case QgsProcessingGui::Standard:
case QgsProcessingGui::Batch:
{
// combobox only for use outside modeler!
mComboBox = new QgsLayoutItemComboBox( nullptr, nullptr );
if ( layoutParam->flags() & QgsProcessingParameterDefinition::FlagOptional )
mComboBox->setAllowEmptyItem( true );
if ( layoutParam->itemType() >= 0 )
mComboBox->setItemType( static_cast< QgsLayoutItemRegistry::ItemType >( layoutParam->itemType() ) );

mComboBox->setToolTip( parameterDefinition()->toolTip() );
connect( mComboBox, &QgsLayoutItemComboBox::itemChanged, this, [ = ]( QgsLayoutItem * )
{
emit widgetValueHasChanged( this );
} );
return mComboBox;
}

case QgsProcessingGui::Modeler:
{
mLineEdit = new QLineEdit();
mLineEdit->setToolTip( tr( "UUID or ID of an existing print layout item" ) );
connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]( const QString & )
{
emit widgetValueHasChanged( this );
} );
return mLineEdit;
}
}
return nullptr;
}

void QgsProcessingLayoutItemWidgetWrapper::postInitialize( const QList<QgsAbstractProcessingParameterWidgetWrapper *> &wrappers )
{
switch ( type() )
{
case QgsProcessingGui::Standard:
case QgsProcessingGui::Batch:
{
for ( const QgsAbstractProcessingParameterWidgetWrapper *wrapper : wrappers )
{
if ( wrapper->parameterDefinition()->name() == static_cast< const QgsProcessingParameterLayoutItem * >( parameterDefinition() )->parentLayoutParameterName() )
{
setLayoutParameterValue( wrapper->parameterValue() );
connect( wrapper, &QgsAbstractProcessingParameterWidgetWrapper::widgetValueHasChanged, this, [ = ]
{
setLayoutParameterValue( wrapper->parameterValue() );
} );
break;
}
}
break;
}

case QgsProcessingGui::Modeler:
break;
}
}

void QgsProcessingLayoutItemWidgetWrapper::setLayoutParameterValue( const QVariant &value )
{
QgsPrintLayout *layout = nullptr;

// evaluate value to layout
QgsProcessingContext *context = nullptr;
std::unique_ptr< QgsProcessingContext > tmpContext;
if ( mProcessingContextGenerator )
context = mProcessingContextGenerator->processingContext();

if ( !context )
{
tmpContext = qgis::make_unique< QgsProcessingContext >();
context = tmpContext.get();
}

layout = QgsProcessingParameters::parameterAsLayout( parameterDefinition(), value, *context );
setLayout( layout );
}

void QgsProcessingLayoutItemWidgetWrapper::setLayout( QgsPrintLayout *layout )
{
if ( mComboBox )
mComboBox->setCurrentLayout( layout );
}

void QgsProcessingLayoutItemWidgetWrapper::setWidgetValue( const QVariant &value, QgsProcessingContext &context )
{
if ( mComboBox )
{
if ( !value.isValid() )
mComboBox->setItem( nullptr );
else
{
QgsLayoutItem *item = QgsProcessingParameters::parameterAsLayoutItem( parameterDefinition(), value, context, qobject_cast< QgsPrintLayout * >( mComboBox->currentLayout() ) );
mComboBox->setItem( item );
}
}
else if ( mLineEdit )
{
const QString v = QgsProcessingParameters::parameterAsString( parameterDefinition(), value, context );
mLineEdit->setText( v );
}
}

QVariant QgsProcessingLayoutItemWidgetWrapper::widgetValue() const
{
if ( mComboBox )
{
const QgsLayoutItem *i = mComboBox->currentItem();
return i ? i->uuid() : QVariant();
}
else if ( mLineEdit )
return mLineEdit->text().isEmpty() ? QVariant() : mLineEdit->text();
else
return QVariant();
}

QStringList QgsProcessingLayoutItemWidgetWrapper::compatibleParameterTypes() const
{
return QStringList()
<< QgsProcessingParameterLayoutItem::typeName()
<< QgsProcessingParameterString::typeName();
}

QStringList QgsProcessingLayoutItemWidgetWrapper::compatibleOutputTypes() const
{
return QStringList()
<< QgsProcessingOutputString::typeName();
}

QList<int> QgsProcessingLayoutItemWidgetWrapper::compatibleDataTypes() const
{
return QList<int>();
}

QString QgsProcessingLayoutItemWidgetWrapper::modelerExpressionFormatString() const
{
return tr( "string representing the UUID or ID of an existing print layout item" );
}

QString QgsProcessingLayoutItemWidgetWrapper::parameterType() const
{
return QgsProcessingParameterLayoutItem::typeName();
}

QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingLayoutItemWidgetWrapper::createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type )
{
return new QgsProcessingLayoutItemWidgetWrapper( parameter, type );
}

///@endcond PRIVATE

0 comments on commit 021d1ef

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