Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Optionally allow entry of new table names in table name parameter
  • Loading branch information
nyalldawson committed Mar 14, 2020
1 parent 55845ee commit 7b1975b
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 15 deletions.
Expand Up @@ -881,6 +881,13 @@ Evaluates the parameter with matching ``name`` to a connection name string.
%Docstring
Evaluates the parameter with matching ``name`` to a database schema name string.

.. versionadded:: 3.14
%End

QString parameterAsDatabaseTableName( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``name`` to a database table name string.

.. versionadded:: 3.14
%End

Expand Down
Expand Up @@ -3798,7 +3798,7 @@ class QgsProcessingParameterDatabaseTable : QgsProcessingParameterDefinition
{
%Docstring
A database table name parameter for processing algorithms, allowing users to select from existing database tables
on a registered database connection.
on a registered database connection (or optionally to enter a new table name).

QgsProcessingParameterDatabaseTable should be evaluated by calling :py:func:`QgsProcessingAlgorithm.parameterAsDatabaseTableName()`

Expand All @@ -3814,7 +3814,8 @@ QgsProcessingParameterDatabaseTable should be evaluated by calling :py:func:`Qgs
const QString &connectionParameterName = QString(),
const QString &schemaParameterName = QString(),
const QVariant &defaultValue = QVariant(),
bool optional = false );
bool optional = false,
bool allowNewTableNames = false );
%Docstring
Constructor for QgsProcessingParameterDatabaseTable.

Expand Down Expand Up @@ -3880,6 +3881,22 @@ Sets the ``name`` of the parent schema parameter. Use an empty string if this is
static QgsProcessingParameterDatabaseTable *fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition ) /Factory/;
%Docstring
Creates a new parameter using the definition from a script code.
%End

bool allowNewTableNames() const;
%Docstring
Returns ``True`` if the parameter allows users to enter names for
a new (non-existing) tables.

.. seealso:: :py:func:`setAllowNewTableNames`
%End

void setAllowNewTableNames( bool allowed );
%Docstring
Sets whether the parameter allows users to enter names for
a new (non-existing) tables.

.. seealso:: :py:func:`allowNewTableNames`
%End

};
Expand Down
5 changes: 5 additions & 0 deletions src/core/processing/qgsprocessingalgorithm.cpp
Expand Up @@ -744,6 +744,11 @@ QString QgsProcessingAlgorithm::parameterAsSchema( const QVariantMap &parameters
return QgsProcessingParameters::parameterAsSchema( parameterDefinition( name ), parameters, context );
}

QString QgsProcessingAlgorithm::parameterAsDatabaseTableName( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context )
{
return QgsProcessingParameters::parameterAsDatabaseTableName( parameterDefinition( name ), parameters, context );
}

QString QgsProcessingAlgorithm::invalidSourceError( const QVariantMap &parameters, const QString &name )
{
if ( !parameters.contains( name ) )
Expand Down
7 changes: 7 additions & 0 deletions src/core/processing/qgsprocessingalgorithm.h
Expand Up @@ -871,6 +871,13 @@ class CORE_EXPORT QgsProcessingAlgorithm
*/
QString parameterAsSchema( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context );

/**
* Evaluates the parameter with matching \a name to a database table name string.
*
* \since QGIS 3.14
*/
QString parameterAsDatabaseTableName( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context );

/**
* Evaluates the parameter with matching \a name to a DateTime, or returns an invalid date time if the parameter was not set.
*
Expand Down
18 changes: 17 additions & 1 deletion src/core/processing/qgsprocessingparameters.cpp
Expand Up @@ -6798,10 +6798,11 @@ QgsProcessingParameterDatabaseSchema *QgsProcessingParameterDatabaseSchema::from
QgsProcessingParameterDatabaseTable::QgsProcessingParameterDatabaseTable( const QString &name, const QString &description,
const QString &connectionParameterName,
const QString &schemaParameterName,
const QVariant &defaultValue, bool optional )
const QVariant &defaultValue, bool optional, bool allowNewTableNames )
: QgsProcessingParameterDefinition( name, description, defaultValue, optional )
, mParentConnectionParameterName( connectionParameterName )
, mParentSchemaParameterName( schemaParameterName )
, mAllowNewTableNames( allowNewTableNames )
{

}
Expand Down Expand Up @@ -6859,6 +6860,9 @@ QString QgsProcessingParameterDatabaseTable::asPythonString( const QgsProcessing
if ( mFlags & FlagOptional )
code += QStringLiteral( ", optional=True" );

if ( mAllowNewTableNames )
code += QStringLiteral( ", allowNewTableNames=True" );

code += QStringLiteral( ", connectionParameterName='%1'" ).arg( mParentConnectionParameterName );
code += QStringLiteral( ", schemaParameterName='%1'" ).arg( mParentSchemaParameterName );
QgsProcessingContext c;
Expand Down Expand Up @@ -6907,6 +6911,7 @@ QVariantMap QgsProcessingParameterDatabaseTable::toVariantMap() const
QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
map.insert( QStringLiteral( "mParentConnectionParameterName" ), mParentConnectionParameterName );
map.insert( QStringLiteral( "mParentSchemaParameterName" ), mParentSchemaParameterName );
map.insert( QStringLiteral( "mAllowNewTableNames" ), mAllowNewTableNames );
return map;
}

Expand All @@ -6915,6 +6920,7 @@ bool QgsProcessingParameterDatabaseTable::fromVariantMap( const QVariantMap &map
QgsProcessingParameterDefinition::fromVariantMap( map );
mParentConnectionParameterName = map.value( QStringLiteral( "mParentConnectionParameterName" ) ).toString();
mParentSchemaParameterName = map.value( QStringLiteral( "mParentSchemaParameterName" ) ).toString();
mAllowNewTableNames = map.value( QStringLiteral( "mAllowNewTableNames" ), false ).toBool();
return true;
}

Expand All @@ -6939,3 +6945,13 @@ QgsProcessingParameterDatabaseTable *QgsProcessingParameterDatabaseTable::fromSc

return new QgsProcessingParameterDatabaseTable( name, description, connection, schema, def.isEmpty() ? QVariant() : def, isOptional );
}

bool QgsProcessingParameterDatabaseTable::allowNewTableNames() const
{
return mAllowNewTableNames;
}

void QgsProcessingParameterDatabaseTable::setAllowNewTableNames( bool allowNewTableNames )
{
mAllowNewTableNames = allowNewTableNames;
}
22 changes: 20 additions & 2 deletions src/core/processing/qgsprocessingparameters.h
Expand Up @@ -3529,7 +3529,7 @@ class CORE_EXPORT QgsProcessingParameterDatabaseSchema : public QgsProcessingPar
* \class QgsProcessingParameterDatabaseTable
* \ingroup core
* A database table name parameter for processing algorithms, allowing users to select from existing database tables
* on a registered database connection.
* on a registered database connection (or optionally to enter a new table name).
*
* QgsProcessingParameterDatabaseTable should be evaluated by calling QgsProcessingAlgorithm::parameterAsDatabaseTableName().
*
Expand All @@ -3552,7 +3552,8 @@ class CORE_EXPORT QgsProcessingParameterDatabaseTable : public QgsProcessingPara
const QString &connectionParameterName = QString(),
const QString &schemaParameterName = QString(),
const QVariant &defaultValue = QVariant(),
bool optional = false );
bool optional = false,
bool allowNewTableNames = false );

/**
* Returns the type name for the parameter class.
Expand Down Expand Up @@ -3597,10 +3598,27 @@ class CORE_EXPORT QgsProcessingParameterDatabaseTable : public QgsProcessingPara
*/
static QgsProcessingParameterDatabaseTable *fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition ) SIP_FACTORY;

/**
* Returns TRUE if the parameter allows users to enter names for
* a new (non-existing) tables.
*
* \see setAllowNewTableNames()
*/
bool allowNewTableNames() const;

/**
* Sets whether the parameter allows users to enter names for
* a new (non-existing) tables.
*
* \see allowNewTableNames()
*/
void setAllowNewTableNames( bool allowed );

private:

QString mParentConnectionParameterName;
QString mParentSchemaParameterName;
bool mAllowNewTableNames = false;
};


Expand Down
11 changes: 2 additions & 9 deletions src/gui/processing/qgsprocessingwidgetwrapperimpl.cpp
Expand Up @@ -4398,15 +4398,8 @@ QWidget *QgsProcessingDatabaseTableWidgetWrapper::createWidget()
if ( tableParam->flags() & QgsProcessingParameterDefinition::FlagOptional )
mTableComboBox->setAllowEmptyTable( true );

switch ( type() )
{
case QgsProcessingGui::Standard:
case QgsProcessingGui::Batch:
break;
case QgsProcessingGui::Modeler:
mTableComboBox->comboBox()->setEditable( true );
break;
}
if ( type() == QgsProcessingGui::Modeler || tableParam->allowNewTableNames() )
mTableComboBox->comboBox()->setEditable( true );

mTableComboBox->setToolTip( parameterDefinition()->toolTip() );
connect( mTableComboBox->comboBox(), &QComboBox::currentTextChanged, this, [ = ]( const QString & )
Expand Down
11 changes: 11 additions & 0 deletions tests/src/analysis/testqgsprocessing.cpp
Expand Up @@ -7166,6 +7166,17 @@ void TestQgsProcessing::parameterDatabaseTable()
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
QCOMPARE( fromCode->parentConnectionParameterName(), def->parentConnectionParameterName() );
QCOMPARE( fromCode->parentSchemaParameterName(), def->parentSchemaParameterName() );

// allow new table names
def.reset( new QgsProcessingParameterDatabaseTable( "new", QString(), QStringLiteral( "con" ), QStringLiteral( "schema" ), QVariant(), false, true ) );

pythonCode = def->asPythonString();
QCOMPARE( pythonCode, QStringLiteral( "QgsProcessingParameterDatabaseTable('new', '', allowNewTableNames=True, connectionParameterName='con', schemaParameterName='schema', defaultValue=None)" ) );
QVariantMap var = def->toVariantMap();
def.reset( dynamic_cast<QgsProcessingParameterDatabaseTable *>( QgsProcessingParameters::parameterFromVariantMap( var ) ) );
QCOMPARE( def->parentConnectionParameterName(), QStringLiteral( "con" ) );
QCOMPARE( def->parentSchemaParameterName(), QStringLiteral( "schema" ) );
QVERIFY( def->allowNewTableNames() );
}

void TestQgsProcessing::parameterDateTime()
Expand Down
32 changes: 31 additions & 1 deletion tests/src/gui/testprocessinggui.cpp
Expand Up @@ -5070,7 +5070,6 @@ void TestProcessingGui::testDatabaseTableWrapper()
}
delete w;


connWrapper.setWidgetValue( QStringLiteral( "aa" ), context );

// optional
Expand All @@ -5095,6 +5094,37 @@ void TestProcessingGui::testDatabaseTableWrapper()
QVERIFY( !wrapper3.widgetValue().isValid() );

delete w;

// allowing new table names
QgsProcessingParameterDatabaseTable param3( QStringLiteral( "table" ), QStringLiteral( "table" ), QStringLiteral( "conn" ), QStringLiteral( "schema" ), QVariant(), false, true );
QgsProcessingDatabaseTableWidgetWrapper wrapper4( &param3, type );
w = wrapper4.createWrappedWidget( context );

wrapper4.setParentConnectionWrapperValue( &connWrapper );
wrapper4.setParentSchemaWrapperValue( &schemaWrapper );

QSignalSpy spy4( &wrapper4, &QgsProcessingDatabaseTableWidgetWrapper::widgetValueHasChanged );
wrapper4.setWidgetValue( QStringLiteral( "someData" ), context );
QCOMPARE( spy4.count(), 1 );
QCOMPARE( wrapper4.widgetValue().toString(), QStringLiteral( "someData" ) );
QCOMPARE( static_cast< QgsDatabaseTableComboBox * >( wrapper4.wrappedWidget() )->comboBox()->currentText(), QStringLiteral( "someData" ) );
wrapper4.setWidgetValue( QStringLiteral( "some_poly_data" ), context );
QCOMPARE( spy4.count(), 2 );
QCOMPARE( wrapper4.widgetValue().toString(), QStringLiteral( "some_poly_data" ) );
QCOMPARE( static_cast< QgsDatabaseTableComboBox * >( wrapper4.wrappedWidget() )->comboBox()->currentText(), QStringLiteral( "some_poly_data" ) );
wrapper4.setWidgetValue( QVariant(), context );
QCOMPARE( spy4.count(), 3 );
QVERIFY( !wrapper4.widgetValue().isValid() );
// should always allow non existing table names
wrapper4.setWidgetValue( QStringLiteral( "someDataxxxxxxxxxxxxxxxxxxxx" ), context );
QCOMPARE( spy4.count(), 4 );
QCOMPARE( wrapper4.widgetValue().toString(), QStringLiteral( "someDataxxxxxxxxxxxxxxxxxxxx" ) );
QCOMPARE( static_cast< QgsDatabaseTableComboBox * >( wrapper4.wrappedWidget() )->comboBox()->currentText(), QStringLiteral( "someDataxxxxxxxxxxxxxxxxxxxx" ) );


delete w;


QLabel *l = wrapper.createWrappedLabel();
if ( wrapper.type() != QgsProcessingGui::Batch )
{
Expand Down

0 comments on commit 7b1975b

Please sign in to comment.