Skip to content
Permalink
Browse files

[feature][processing] Add modeler algorithm to create directories

This algorithm allows models to create new file directories. Useful for
models which have to output results to certain dynamically created paths
(e.g. a folder containing the current date)
  • Loading branch information
nyalldawson committed Jun 28, 2020
1 parent 2204399 commit da8fa08af5283f9b338bbe7b2ae63e67090570ee
@@ -42,6 +42,7 @@ SET(QGIS_ANALYSIS_SRCS
processing/qgsalgorithmconstantraster.cpp
processing/qgsalgorithmconverttocurves.cpp
processing/qgsalgorithmconvexhull.cpp
processing/qgsalgorithmcreatedirectory.cpp
processing/qgsalgorithmdbscanclustering.cpp
processing/qgsalgorithmdeleteduplicategeometries.cpp
processing/qgsalgorithmdensifygeometriesbycount.cpp
@@ -0,0 +1,104 @@
/***************************************************************************
qgsalgorithmcreatedirectory.cpp
---------------------
begin : June 2020
copyright : (C) 2020 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsalgorithmcreatedirectory.h"

///@cond PRIVATE

QString QgsCreateDirectoryAlgorithm::name() const
{
return QStringLiteral( "createdirectory" );
}

QgsProcessingAlgorithm::Flags QgsCreateDirectoryAlgorithm::flags() const
{
return FlagHideFromToolbox | FlagSkipGenericModelLogging;
}

QString QgsCreateDirectoryAlgorithm::displayName() const
{
return QObject::tr( "Create directory" );
}

QStringList QgsCreateDirectoryAlgorithm::tags() const
{
return QObject::tr( "new,make,folder" ).split( ',' );
}

QString QgsCreateDirectoryAlgorithm::group() const
{
return QObject::tr( "File tools" );
}

QString QgsCreateDirectoryAlgorithm::groupId() const
{
return QStringLiteral( "filetools" );
}

QString QgsCreateDirectoryAlgorithm::shortHelpString() const
{
return QObject::tr( "This algorithm creates a new directory on a file system. Directories will be created recursively, creating all "
"required parent directories in order to construct the full specified directory path.\n\n"
"No errors will be raised if the directory already exists." );
}

QString QgsCreateDirectoryAlgorithm::shortDescription() const
{
return QObject::tr( "Creates a new directory on a file system." );
}

QgsCreateDirectoryAlgorithm *QgsCreateDirectoryAlgorithm::createInstance() const
{
return new QgsCreateDirectoryAlgorithm();
}

void QgsCreateDirectoryAlgorithm::initAlgorithm( const QVariantMap & )
{
addParameter( new QgsProcessingParameterMapLayer( QStringLiteral( "PATH" ), QObject::tr( "Directory path" ) ) );
addOutput( new QgsProcessingOutputFolder( QStringLiteral( "OUTPUT" ), QObject::tr( "Directory" ) ) );
}

QVariantMap QgsCreateDirectoryAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
const QString path = parameterAsString( parameters, QStringLiteral( "PATH" ), context );

if ( !path.isEmpty() )
{
if ( QFile::exists( path ) )
{
if ( !QFileInfo( path ).isDir() )
throw QgsProcessingException( QObject::tr( "A file with the name %1 already exists -- cannot create a new directory here." ).arg( path ) );
if ( feedback )
feedback->pushInfo( QObject::tr( "The directory %1 already exists." ).arg( path ) );
}
else
{
if ( !QDir().mkpath( path ) )
{
throw QgsProcessingException( QObject::tr( "Could not create directory %1. Please check that you have write permissions for the specified path." ).arg( path ) );
}

if ( feedback )
feedback->pushInfo( QObject::tr( "Created %1" ).arg( path ) );
}
}

QVariantMap results;
results.insert( QStringLiteral( "OUTPUT" ), path );
return results;
}

///@endcond
@@ -0,0 +1,55 @@
/***************************************************************************
qgsalgorithmcreatedirectory.h
---------------------
begin : June 2020
copyright : (C) 2020 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSALGORITHMCREATEDIRECTORY_H
#define QGSALGORITHMCREATEDIRECTORY_H

#define SIP_NO_FILE

#include "qgis_sip.h"
#include "qgsprocessingalgorithm.h"

///@cond PRIVATE

/**
* Native create directory algorithm.
*/
class QgsCreateDirectoryAlgorithm : public QgsProcessingAlgorithm
{
public:
QgsCreateDirectoryAlgorithm() = default;
void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override;
Flags flags() const override;
QString name() const override;
QString displayName() const override;
QStringList tags() const override;
QString group() const override;
QString groupId() const override;
QString shortHelpString() const override;
QString shortDescription() const override;
QgsCreateDirectoryAlgorithm *createInstance() const override SIP_FACTORY;

protected:

QVariantMap processAlgorithm( const QVariantMap &parameters,
QgsProcessingContext &context, QgsProcessingFeedback * ) override;

};

///@endcond PRIVATE

#endif // QGSALGORITHMCREATEDIRECTORY_H
@@ -38,6 +38,7 @@
#include "qgsalgorithmconstantraster.h"
#include "qgsalgorithmconverttocurves.h"
#include "qgsalgorithmconvexhull.h"
#include "qgsalgorithmcreatedirectory.h"
#include "qgsalgorithmdbscanclustering.h"
#include "qgsalgorithmdeleteduplicategeometries.h"
#include "qgsalgorithmdensifygeometriesbycount.h"
@@ -249,6 +250,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
addAlgorithm( new QgsConstantRasterAlgorithm() );
addAlgorithm( new QgsConvertToCurvesAlgorithm() );
addAlgorithm( new QgsConvexHullAlgorithm() );
addAlgorithm( new QgsCreateDirectoryAlgorithm() );
addAlgorithm( new QgsDbscanClusteringAlgorithm() );
addAlgorithm( new QgsDeleteDuplicateGeometriesAlgorithm() );
addAlgorithm( new QgsDetectVectorChangesAlgorithm() );
@@ -81,6 +81,7 @@ class TestQgsProcessingAlgs: public QObject
void kmeansCluster();
void categorizeByStyle();
void extractBinary();
void createDirectory();

void polygonsToLines_data();
void polygonsToLines();
@@ -825,6 +826,50 @@ void TestQgsProcessingAlgs::extractBinary()
QCOMPARE( QString( QCryptographicHash::hash( d, QCryptographicHash::Md5 ).toHex() ), QStringLiteral( "4b952b80e4288ca5111be2f6dd5d6809" ) );
}

void TestQgsProcessingAlgs::createDirectory()
{
std::unique_ptr< QgsProcessingAlgorithm > alg( QgsApplication::processingRegistry()->createAlgorithmById( QStringLiteral( "native:createdirectory" ) ) );
QVERIFY( alg != nullptr );

// first make a path to an existing file
QString outputPath = QDir::tempPath() + "/test.txt";
if ( QFile::exists( outputPath ) )
QFile::remove( outputPath );
QFile file( outputPath );
file.open( QIODevice::ReadWrite );
file.close();

QVariantMap parameters;
parameters.insert( QStringLiteral( "PATH" ), outputPath );

bool ok = false;
std::unique_ptr< QgsProcessingContext > context = qgis::make_unique< QgsProcessingContext >();
QgsProcessingFeedback feedback;
QVariantMap results;
results = alg->run( parameters, *context, &feedback, &ok );
// path is an existing file
QVERIFY( !ok );

outputPath = QDir::tempPath() + "/createdir/test/test2";
QDir().rmdir( QDir::tempPath() + "/createdir/test/test2" );
QDir().rmdir( QDir::tempPath() + "/createdir/test" );
QDir().rmdir( QDir::tempPath() + "/createdir" );

parameters.insert( QStringLiteral( "PATH" ), outputPath );
results = alg->run( parameters, *context, &feedback, &ok );
QVERIFY( ok );

QVERIFY( QFile::exists( outputPath ) );
QVERIFY( QFileInfo( outputPath ).isDir() );

// run a second time -- should be OK, no exception raised
results = alg->run( parameters, *context, &feedback, &ok );
QVERIFY( ok );

QVERIFY( QFile::exists( outputPath ) );
QVERIFY( QFileInfo( outputPath ).isDir() );
}


void TestQgsProcessingAlgs::polygonsToLines_data()
{

0 comments on commit da8fa08

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