Skip to content

Commit

Permalink
[FEATURE] Expression functions which return file info
Browse files Browse the repository at this point in the history
base_file_name: Returns the base name of the file without the directory or file suffix.
file_exists: Returns true if a file exists
file_name: Returns the file name from a full path
file_path: Returns the directory/path from a full file path
file_size: Returns a file size
file_suffix: Returns a files suffix/extension
is_directory: Returns true if a file path is a directory
is_file: Returns true if a file path is a file
  • Loading branch information
nyalldawson committed Apr 27, 2019
1 parent 7e5f906 commit 762b2a4
Show file tree
Hide file tree
Showing 10 changed files with 171 additions and 1 deletion.
8 changes: 8 additions & 0 deletions resources/function_help/json/base_file_name
@@ -0,0 +1,8 @@
{
"name": "base_file_name",
"type": "function",
"description": "Returns the base name of the file without the directory or file suffix.",
"arguments": [ {"arg":"path","description":"a file path"}],
"examples": [ { "expression":"base_file_name('/home/qgis/data/country_boundaries.shp')", "returns":"'country_boundaries'"}]
}

8 changes: 8 additions & 0 deletions resources/function_help/json/file_exists
@@ -0,0 +1,8 @@
{
"name": "file_exists",
"type": "function",
"description": "Returns true if a file path exists.",
"arguments": [ {"arg":"path","description":"a file path"}],
"examples": [ { "expression":"file_exists('/home/qgis/data/country_boundaries.shp')", "returns":"true"}]
}

8 changes: 8 additions & 0 deletions resources/function_help/json/file_name
@@ -0,0 +1,8 @@
{
"name": "file_name",
"type": "function",
"description": "Returns the name of a file (including the file extension), excluding the directory.",
"arguments": [ {"arg":"path","description":"a file path"}],
"examples": [ { "expression":"base_file_name('/home/qgis/data/country_boundaries.shp')", "returns":"'country_boundaries.shp'"}]
}

8 changes: 8 additions & 0 deletions resources/function_help/json/file_path
@@ -0,0 +1,8 @@
{
"name": "file_path",
"type": "function",
"description": "Returns the directory component of a file path. This does not include the file name.",
"arguments": [ {"arg":"path","description":"a file path"}],
"examples": [ { "expression":"base_file_name('/home/qgis/data/country_boundaries.shp')", "returns":"'/home/qgis/data'"}]
}

8 changes: 8 additions & 0 deletions resources/function_help/json/file_size
@@ -0,0 +1,8 @@
{
"name": "file_size",
"type": "function",
"description": "Returns the size (in bytes) of a file.",
"arguments": [ {"arg":"path","description":"a file path"}],
"examples": [ { "expression":"file_size('/home/qgis/data/country_boundaries.geojson')", "returns":"5674"}]
}

8 changes: 8 additions & 0 deletions resources/function_help/json/file_suffix
@@ -0,0 +1,8 @@
{
"name": "file_suffix",
"type": "function",
"description": "Returns the file suffix (extension) from a file path.",
"arguments": [ {"arg":"path","description":"a file path"}],
"examples": [ { "expression":"base_file_name('/home/qgis/data/country_boundaries.shp')", "returns":"'shp'"}]
}

9 changes: 9 additions & 0 deletions resources/function_help/json/is_directory
@@ -0,0 +1,9 @@
{
"name": "is_directory",
"type": "function",
"description": "Returns true if a path corresponds to a directory.",
"arguments": [ {"arg":"path","description":"a file path"}],
"examples": [ { "expression":"is_directory('/home/qgis/data/country_boundaries.shp')", "returns":"false"},
{ "expression":"is_directory('/home/qgis/data/')", "returns":"true"}]
}

9 changes: 9 additions & 0 deletions resources/function_help/json/is_file
@@ -0,0 +1,9 @@
{
"name": "is_file",
"type": "function",
"description": "Returns true if a path corresponds to a file.",
"arguments": [ {"arg":"path","description":"a file path"}],
"examples": [ { "expression":"is_file('/home/qgis/data/country_boundaries.shp')", "returns":"true"},
{ "expression":"is_file('/home/qgis/data/')", "returns":"false"}]
}

69 changes: 69 additions & 0 deletions src/core/expression/qgsexpressionfunction.cpp
Expand Up @@ -4782,6 +4782,57 @@ static QVariant fcnEnvVar( const QVariantList &values, const QgsExpressionContex
return QProcessEnvironment::systemEnvironment().value( envVarName ); return QProcessEnvironment::systemEnvironment().value( envVarName );
} }


static QVariant fcnBaseFileName( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
const QString file = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
return QFileInfo( file ).completeBaseName();
}

static QVariant fcnFileSuffix( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
const QString file = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
return QFileInfo( file ).completeSuffix();
}

static QVariant fcnFileExists( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
const QString file = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
return QFileInfo::exists( file );
}

static QVariant fcnFileName( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
const QString file = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
return QFileInfo( file ).fileName();
}

static QVariant fcnPathIsFile( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
const QString file = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
return QFileInfo( file ).isFile();
}

static QVariant fcnPathIsDir( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
const QString file = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
return QFileInfo( file ).isDir();
}

static QVariant fcnFilePath( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
const QString file = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
return QDir::toNativeSeparators( QFileInfo( file ).path() );
}

static QVariant fcnFileSize( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
const QString file = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
return QFileInfo( file ).size();
}




const QList<QgsExpressionFunction *> &QgsExpression::Functions() const QList<QgsExpressionFunction *> &QgsExpression::Functions()
{ {
// The construction of the list isn't thread-safe, and without the mutex, // The construction of the list isn't thread-safe, and without the mutex,
Expand Down Expand Up @@ -5045,6 +5096,24 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
fncLighter, QStringLiteral( "Color" ) ) fncLighter, QStringLiteral( "Color" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "set_color_part" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "color" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "component" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "value" ) ), fncSetColorPart, QStringLiteral( "Color" ) ) << new QgsStaticExpressionFunction( QStringLiteral( "set_color_part" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "color" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "component" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "value" ) ), fncSetColorPart, QStringLiteral( "Color" ) )


// file info
<< new QgsStaticExpressionFunction( QStringLiteral( "base_file_name" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "path" ) ),
fcnBaseFileName, QStringLiteral( "Files and Paths" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "file_suffix" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "path" ) ),
fcnFileSuffix, QStringLiteral( "Files and Paths" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "file_exists" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "path" ) ),
fcnFileExists, QStringLiteral( "Files and Paths" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "file_name" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "path" ) ),
fcnFileName, QStringLiteral( "Files and Paths" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "is_file" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "path" ) ),
fcnPathIsFile, QStringLiteral( "Files and Paths" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "is_directory" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "path" ) ),
fcnPathIsDir, QStringLiteral( "Files and Paths" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "file_path" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "path" ) ),
fcnFilePath, QStringLiteral( "Files and Paths" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "file_size" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "path" ) ),
fcnFileSize, QStringLiteral( "Files and Paths" ) )

// deprecated stuff - hidden from users // deprecated stuff - hidden from users
<< new QgsStaticExpressionFunction( QStringLiteral( "$scale" ), QgsExpressionFunction::ParameterList(), fcnMapScale, QStringLiteral( "deprecated" ) ); << new QgsStaticExpressionFunction( QStringLiteral( "$scale" ), QgsExpressionFunction::ParameterList(), fcnMapScale, QStringLiteral( "deprecated" ) );


Expand Down
37 changes: 36 additions & 1 deletion tests/src/core/testqgsexpression.cpp
Expand Up @@ -1370,9 +1370,44 @@ class TestQgsExpression: public QObject
QTest::newRow( "array_last(array('a', 'b', 'c'))" ) << QStringLiteral( "array_last(array('a', 'b', 'c'))" ) << false << QVariant( "c" ); QTest::newRow( "array_last(array('a', 'b', 'c'))" ) << QStringLiteral( "array_last(array('a', 'b', 'c'))" ) << false << QVariant( "c" );
QTest::newRow( "array_last(array())" ) << QStringLiteral( "array_last(array())" ) << false << QVariant(); QTest::newRow( "array_last(array())" ) << QStringLiteral( "array_last(array())" ) << false << QVariant();


// // file functions
QTest::newRow( "base_file_name(5)" ) << QStringLiteral( "base_file_name(5)" ) << false << QVariant( "5" );
QTest::newRow( "base_file_name(NULL)" ) << QStringLiteral( "base_file_name(NULL)" ) << false << QVariant();
QTest::newRow( "base_file_name('/home/qgis/test.qgs')" ) << QStringLiteral( "base_file_name('/home/qgis/test.qgs')" ) << false << QVariant( "test" );
QTest::newRow( "base_file_name(points.shp)" ) << QStringLiteral( "base_file_name('%1/points.shp')" ).arg( TEST_DATA_DIR ) << false << QVariant( "points" );
QTest::newRow( "file_exists(NULL)" ) << QStringLiteral( "file_exists(NULL)" ) << false << QVariant();
QTest::newRow( "file_exists('/home/qgis/test.qgs')" ) << QStringLiteral( "file_exists('/home/qgis/test.qgs')" ) << false << QVariant( false );
QTest::newRow( "file_exists(points.shp)" ) << QStringLiteral( "file_exists('%1/points.shp')" ).arg( TEST_DATA_DIR ) << false << QVariant( true );
QTest::newRow( "file_name(5)" ) << QStringLiteral( "file_name(5)" ) << false << QVariant( "5" );
QTest::newRow( "file_name(NULL)" ) << QStringLiteral( "file_name(NULL)" ) << false << QVariant();
QTest::newRow( "file_name('/home/qgis/test.qgs')" ) << QStringLiteral( "file_name('/home/qgis/test.qgs')" ) << false << QVariant( "test.qgs" );
QTest::newRow( "file_name(points.shp)" ) << QStringLiteral( "file_name('%1/points.shp')" ).arg( TEST_DATA_DIR ) << false << QVariant( "points.shp" );
QTest::newRow( "file_path(5)" ) << QStringLiteral( "file_path(5)" ) << false << QVariant( "." );
QTest::newRow( "file_path(NULL)" ) << QStringLiteral( "file_path(NULL)" ) << false << QVariant();
QTest::newRow( "file_path('/home/qgis/test.qgs')" ) << QStringLiteral( "file_path('/home/qgis/test.qgs')" ) << false << QVariant( "/home/qgis" );
QTest::newRow( "file_path(points.shp)" ) << QStringLiteral( "file_path('%1/points.shp')" ).arg( TEST_DATA_DIR ) << false << QVariant( TEST_DATA_DIR );
QTest::newRow( "file_size(5)" ) << QStringLiteral( "file_size(5)" ) << false << QVariant( 0LL );
QTest::newRow( "file_size(NULL)" ) << QStringLiteral( "file_size(NULL)" ) << false << QVariant();
QTest::newRow( "file_size('/home/qgis/test.qgs')" ) << QStringLiteral( "file_size('/home/qgis/test.qgs')" ) << false << QVariant( 0LL );
QTest::newRow( "file_size(points.shp)" ) << QStringLiteral( "file_size('%1/points.shp')" ).arg( TEST_DATA_DIR ) << false << QVariant( 576LL );
QTest::newRow( "file_suffix(5)" ) << QStringLiteral( "file_suffix(5)" ) << false << QVariant( "" );
QTest::newRow( "file_suffix(NULL)" ) << QStringLiteral( "file_suffix(NULL)" ) << false << QVariant();
QTest::newRow( "file_suffix('/home/qgis/test.qgs')" ) << QStringLiteral( "file_suffix('/home/qgis/test.qgs')" ) << false << QVariant( "qgs" );
QTest::newRow( "file_suffix(points.shp)" ) << QStringLiteral( "file_suffix('%1/points.shp')" ).arg( TEST_DATA_DIR ) << false << QVariant( "shp" );
QTest::newRow( "is_directory(5)" ) << QStringLiteral( "is_directory(5)" ) << false << QVariant( false );
QTest::newRow( "is_directory(NULL)" ) << QStringLiteral( "is_directory(NULL)" ) << false << QVariant();
QTest::newRow( "is_directory('/home/qgis/test.qgs')" ) << QStringLiteral( "is_directory('/home/qgis/test.qgs')" ) << false << QVariant( false );
QTest::newRow( "is_directory(points.shp)" ) << QStringLiteral( "is_directory('%1/points.shp')" ).arg( TEST_DATA_DIR ) << false << QVariant( false );
QTest::newRow( "is_directory(valid)" ) << QStringLiteral( "is_directory('%1')" ).arg( TEST_DATA_DIR ) << false << QVariant( true );
QTest::newRow( "is_file(5)" ) << QStringLiteral( "is_file(5)" ) << false << QVariant( false );
QTest::newRow( "is_file(NULL)" ) << QStringLiteral( "is_file(NULL)" ) << false << QVariant();
QTest::newRow( "is_file('/home/qgis/test.qgs')" ) << QStringLiteral( "is_file('/home/qgis/test.qgs')" ) << false << QVariant( false );
QTest::newRow( "is_file(points.shp)" ) << QStringLiteral( "is_file('%1/points.shp')" ).arg( TEST_DATA_DIR ) << false << QVariant( true );
QTest::newRow( "is_file(valid)" ) << QStringLiteral( "is_file('%1')" ).arg( TEST_DATA_DIR ) << false << QVariant( false );

} }



void run_evaluation_test( QgsExpression &exp, bool evalError, QVariant &expected ) void run_evaluation_test( QgsExpression &exp, bool evalError, QVariant &expected )
{ {
if ( exp.hasParserError() ) if ( exp.hasParserError() )
Expand Down

0 comments on commit 762b2a4

Please sign in to comment.