From 7b1975ba83336f7406921b0187a05789d539c0c4 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Fri, 13 Mar 2020 18:53:45 +1000 Subject: [PATCH] Optionally allow entry of new table names in table name parameter --- .../processing/qgsprocessingalgorithm.sip.in | 7 ++++ .../processing/qgsprocessingparameters.sip.in | 21 ++++++++++-- .../processing/qgsprocessingalgorithm.cpp | 5 +++ src/core/processing/qgsprocessingalgorithm.h | 7 ++++ .../processing/qgsprocessingparameters.cpp | 18 ++++++++++- src/core/processing/qgsprocessingparameters.h | 22 +++++++++++-- .../qgsprocessingwidgetwrapperimpl.cpp | 11 ++----- tests/src/analysis/testqgsprocessing.cpp | 11 +++++++ tests/src/gui/testprocessinggui.cpp | 32 ++++++++++++++++++- 9 files changed, 119 insertions(+), 15 deletions(-) diff --git a/python/core/auto_generated/processing/qgsprocessingalgorithm.sip.in b/python/core/auto_generated/processing/qgsprocessingalgorithm.sip.in index b03b6da590a..9304f71001b 100644 --- a/python/core/auto_generated/processing/qgsprocessingalgorithm.sip.in +++ b/python/core/auto_generated/processing/qgsprocessingalgorithm.sip.in @@ -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 ¶meters, const QString &name, QgsProcessingContext &context ); +%Docstring +Evaluates the parameter with matching ``name`` to a database table name string. + .. versionadded:: 3.14 %End diff --git a/python/core/auto_generated/processing/qgsprocessingparameters.sip.in b/python/core/auto_generated/processing/qgsprocessingparameters.sip.in index a939a6b1dad..1975d943d47 100644 --- a/python/core/auto_generated/processing/qgsprocessingparameters.sip.in +++ b/python/core/auto_generated/processing/qgsprocessingparameters.sip.in @@ -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()` @@ -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. @@ -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 }; diff --git a/src/core/processing/qgsprocessingalgorithm.cpp b/src/core/processing/qgsprocessingalgorithm.cpp index 85c91533b70..5eb4485717a 100644 --- a/src/core/processing/qgsprocessingalgorithm.cpp +++ b/src/core/processing/qgsprocessingalgorithm.cpp @@ -744,6 +744,11 @@ QString QgsProcessingAlgorithm::parameterAsSchema( const QVariantMap ¶meters return QgsProcessingParameters::parameterAsSchema( parameterDefinition( name ), parameters, context ); } +QString QgsProcessingAlgorithm::parameterAsDatabaseTableName( const QVariantMap ¶meters, const QString &name, QgsProcessingContext &context ) +{ + return QgsProcessingParameters::parameterAsDatabaseTableName( parameterDefinition( name ), parameters, context ); +} + QString QgsProcessingAlgorithm::invalidSourceError( const QVariantMap ¶meters, const QString &name ) { if ( !parameters.contains( name ) ) diff --git a/src/core/processing/qgsprocessingalgorithm.h b/src/core/processing/qgsprocessingalgorithm.h index ef6792af962..9925ee61025 100644 --- a/src/core/processing/qgsprocessingalgorithm.h +++ b/src/core/processing/qgsprocessingalgorithm.h @@ -871,6 +871,13 @@ class CORE_EXPORT QgsProcessingAlgorithm */ QString parameterAsSchema( const QVariantMap ¶meters, 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 ¶meters, 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. * diff --git a/src/core/processing/qgsprocessingparameters.cpp b/src/core/processing/qgsprocessingparameters.cpp index 6b1ef0ca00c..961543a0e3e 100644 --- a/src/core/processing/qgsprocessingparameters.cpp +++ b/src/core/processing/qgsprocessingparameters.cpp @@ -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 ) { } @@ -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; @@ -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; } @@ -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; } @@ -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; +} diff --git a/src/core/processing/qgsprocessingparameters.h b/src/core/processing/qgsprocessingparameters.h index 391dbd64a7c..fce9415c194 100644 --- a/src/core/processing/qgsprocessingparameters.h +++ b/src/core/processing/qgsprocessingparameters.h @@ -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(). * @@ -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. @@ -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; }; diff --git a/src/gui/processing/qgsprocessingwidgetwrapperimpl.cpp b/src/gui/processing/qgsprocessingwidgetwrapperimpl.cpp index 96f43f0a4f9..ff92b8a37c5 100644 --- a/src/gui/processing/qgsprocessingwidgetwrapperimpl.cpp +++ b/src/gui/processing/qgsprocessingwidgetwrapperimpl.cpp @@ -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 & ) diff --git a/tests/src/analysis/testqgsprocessing.cpp b/tests/src/analysis/testqgsprocessing.cpp index a8863e369b3..22b65a93eca 100644 --- a/tests/src/analysis/testqgsprocessing.cpp +++ b/tests/src/analysis/testqgsprocessing.cpp @@ -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( QgsProcessingParameters::parameterFromVariantMap( var ) ) ); + QCOMPARE( def->parentConnectionParameterName(), QStringLiteral( "con" ) ); + QCOMPARE( def->parentSchemaParameterName(), QStringLiteral( "schema" ) ); + QVERIFY( def->allowNewTableNames() ); } void TestQgsProcessing::parameterDateTime() diff --git a/tests/src/gui/testprocessinggui.cpp b/tests/src/gui/testprocessinggui.cpp index a98342e2b53..f1783f15e74 100644 --- a/tests/src/gui/testprocessinggui.cpp +++ b/tests/src/gui/testprocessinggui.cpp @@ -5070,7 +5070,6 @@ void TestProcessingGui::testDatabaseTableWrapper() } delete w; - connWrapper.setWidgetValue( QStringLiteral( "aa" ), context ); // optional @@ -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( ¶m3, 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 ) {