Skip to content

Commit

Permalink
Add some extension and filter handling functions to QgsFileUtils
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Dec 19, 2017
1 parent 48e6ec5 commit 128e37e
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 0 deletions.
39 changes: 39 additions & 0 deletions python/core/qgsfileutils.sip
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,45 @@ class QgsFileUtils
Return the human size from bytes
%End


static QStringList extensionsFromFilter( const QString &filter );
%Docstring
Returns a list of the extensions contained within a file ``filter`` string.
E.g. a ``filter`` of "GeoTIFF Files (*.tiff *.tif)" would return a list
containing "tiff", "tif". The initial '.' is stripped off the extension.

.. seealso:: :py:func:`ensureFileNameHasExtension()`

.. seealso:: :py:func:`addExtensionFromFilter()`
%End

static QString ensureFileNameHasExtension( const QString &fileName, const QStringList &extensions );
%Docstring
Ensures that a ``fileName`` ends with an extension from the provided list of
``extensions``.

E.g. if extensions contains "tif" and "tiff", then a ``fileName`` of
"d:/my_file" will return "d:/my_file.tif". A ``fileName`` of
"d:/my_file.TIFF" or "d:/my_file.TIF" will be returned unchanged.

.. seealso:: :py:func:`extensionsFromFilter()`

.. seealso:: :py:func:`addExtensionFromFilter()`
%End

static QString addExtensionFromFilter( const QString &fileName, const QString &filter );
%Docstring
Ensures that a ``fileName`` ends with an extension from the specified ``filter``
string.

E.g. a ``fileName`` of "d:/my_file" with a filter of "GeoTIFF Files (*.tiff *.tif)"
will return "d:/my_file.tif", where as ``fileName`` of "d:/my_file.TIFF" or "d:/my_file.TIF"
will be returned unchanged.

.. seealso:: :py:func:`extensionsFromFilter()`

.. seealso:: :py:func:`ensureFileNameHasExtension()`
%End
};

/************************************************************************
Expand Down
53 changes: 53 additions & 0 deletions src/core/qgsfileutils.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "qgsfileutils.h"
#include <QObject>
#include <QRegularExpression>

QString QgsFileUtils::representFileSize( qint64 bytes )
{
Expand All @@ -16,3 +17,55 @@ QString QgsFileUtils::representFileSize( qint64 bytes )
}
return QString( "%1 %2" ).arg( QString::number( bytes ), unit );
}

QStringList QgsFileUtils::extensionsFromFilter( const QString &filter )
{
const QRegularExpression rx( QStringLiteral( "\\*\\.([a-zA-Z0-9]+)" ) );
QStringList extensions;
QRegularExpressionMatchIterator matches = rx.globalMatch( filter );

while ( matches.hasNext() )
{
const QRegularExpressionMatch match = matches.next();
if ( match.hasMatch() )
{
QStringList newExtensions = match.capturedTexts();
newExtensions.pop_front(); // remove whole match
extensions.append( newExtensions );
}
}
return extensions;
}

QString QgsFileUtils::ensureFileNameHasExtension( const QString &f, const QStringList &extensions )
{
if ( extensions.empty() || f.isEmpty() )
return f;

QString fileName = f;
bool hasExt = false;
for ( const QString &extension : qgis::as_const( extensions ) )
{
const QString extWithDot = extension.startsWith( '.' ) ? extension : '.' + extension;
if ( fileName.endsWith( extWithDot, Qt::CaseInsensitive ) )
{
hasExt = true;
break;
}
}

if ( !hasExt )
{
const QString extension = extensions.at( 0 );
const QString extWithDot = extension.startsWith( '.' ) ? extension : '.' + extension;
fileName += extWithDot;
}

return fileName;
}

QString QgsFileUtils::addExtensionFromFilter( const QString &fileName, const QString &filter )
{
const QStringList extensions = extensionsFromFilter( filter );
return ensureFileNameHasExtension( fileName, extensions );
}
35 changes: 35 additions & 0 deletions src/core/qgsfileutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,41 @@ class CORE_EXPORT QgsFileUtils
*/
static QString representFileSize( qint64 bytes );


/**
* Returns a list of the extensions contained within a file \a filter string.
* E.g. a \a filter of "GeoTIFF Files (*.tiff *.tif)" would return a list
* containing "tiff", "tif". The initial '.' is stripped off the extension.
* \see ensureFileNameHasExtension()
* \see addExtensionFromFilter()
*/
static QStringList extensionsFromFilter( const QString &filter );

/**
* Ensures that a \a fileName ends with an extension from the provided list of
* \a extensions.
*
* E.g. if extensions contains "tif" and "tiff", then a \a fileName of
* "d:/my_file" will return "d:/my_file.tif". A \a fileName of
* "d:/my_file.TIFF" or "d:/my_file.TIF" will be returned unchanged.
*
* \see extensionsFromFilter()
* \see addExtensionFromFilter()
*/
static QString ensureFileNameHasExtension( const QString &fileName, const QStringList &extensions );

/**
* Ensures that a \a fileName ends with an extension from the specified \a filter
* string.
*
* E.g. a \a fileName of "d:/my_file" with a filter of "GeoTIFF Files (*.tiff *.tif)"
* will return "d:/my_file.tif", where as \a fileName of "d:/my_file.TIFF" or "d:/my_file.TIF"
* will be returned unchanged.
*
* \see extensionsFromFilter()
* \see ensureFileNameHasExtension()
*/
static QString addExtensionFromFilter( const QString &fileName, const QString &filter );
};

#endif // QGSFILEUTILS_H
60 changes: 60 additions & 0 deletions tests/src/python/test_qgsfileutils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
"""QGIS Unit tests for QgsFileUtils.
.. note:: 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.
"""
__author__ = 'Nyall Dawson'
__date__ = '18/12/2017'
__copyright__ = 'Copyright 2017, The QGIS Project'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'

import qgis # NOQA

from qgis.core import QgsFileUtils
from qgis.testing import unittest


class TestQgsFileUtils(unittest.TestCase):

def testExtensionsFromFilter(self):
self.assertEqual(QgsFileUtils.extensionsFromFilter(''), [])
self.assertEqual(QgsFileUtils.extensionsFromFilter('bad'), [])
self.assertEqual(QgsFileUtils.extensionsFromFilter('*'), [])
self.assertEqual(QgsFileUtils.extensionsFromFilter('*.'), [])
self.assertEqual(QgsFileUtils.extensionsFromFilter('Tiff files'), [])
self.assertEqual(QgsFileUtils.extensionsFromFilter('(*.)'), [])
self.assertEqual(QgsFileUtils.extensionsFromFilter('PNG Files (*.png)'), ['png'])
self.assertEqual(QgsFileUtils.extensionsFromFilter('PNG Files (*.PNG)'), ['PNG'])
self.assertEqual(QgsFileUtils.extensionsFromFilter('Geotiff Files (*.tiff *.tif)'), ['tiff', 'tif'])

def testEnsureFileNameHasExtension(self):
self.assertEqual(QgsFileUtils.ensureFileNameHasExtension('', ['']), '')
self.assertEqual(QgsFileUtils.ensureFileNameHasExtension('', []), '')
self.assertEqual(QgsFileUtils.ensureFileNameHasExtension('test', []), 'test')
self.assertEqual(QgsFileUtils.ensureFileNameHasExtension('', ['.tif']), '')
self.assertEqual(QgsFileUtils.ensureFileNameHasExtension('test', ['.tif']), 'test.tif')
self.assertEqual(QgsFileUtils.ensureFileNameHasExtension('test', ['tif']), 'test.tif')
self.assertEqual(QgsFileUtils.ensureFileNameHasExtension('test.tif', []), 'test.tif')
self.assertEqual(QgsFileUtils.ensureFileNameHasExtension('test.tif', ['bmp']), 'test.tif.bmp')
self.assertEqual(QgsFileUtils.ensureFileNameHasExtension('test.tif', ['tiff']), 'test.tif.tiff')
self.assertEqual(QgsFileUtils.ensureFileNameHasExtension('test.tif', ['tiff', 'tif']), 'test.tif')
self.assertEqual(QgsFileUtils.ensureFileNameHasExtension('test.tif', ['TIFF', 'TIF']), 'test.tif')

def testAddExtensionFromFilter(self):
self.assertEqual(QgsFileUtils.addExtensionFromFilter('test', 'TIFF Files (*.tif)'), 'test.tif')
self.assertEqual(QgsFileUtils.addExtensionFromFilter('test', 'TIFF Files (*.tif)'), 'test.tif')
self.assertEqual(QgsFileUtils.addExtensionFromFilter('test.tif', ''), 'test.tif')
self.assertEqual(QgsFileUtils.addExtensionFromFilter('test.tif', 'BMP Files (*.bmp)'), 'test.tif.bmp')
self.assertEqual(QgsFileUtils.addExtensionFromFilter('test.tif', 'TIFF Files (*.tiff)'), 'test.tif.tiff')
self.assertEqual(QgsFileUtils.addExtensionFromFilter('test.tif', 'TIFF Files (*.tif *.tiff)'), 'test.tif')
self.assertEqual(QgsFileUtils.addExtensionFromFilter('test.tif', 'TIFF Files (*.TIF *.TIFF)'), 'test.tif')
self.assertEqual(QgsFileUtils.addExtensionFromFilter('test.tif', 'All Files (*.*)'), 'test.tif')
self.assertEqual(QgsFileUtils.addExtensionFromFilter('test', 'All Files (*.*)'), 'test')


if __name__ == '__main__':
unittest.main()

0 comments on commit 128e37e

Please sign in to comment.