QGIS API Documentation  3.4.15-Madeira (e83d02e274)
qgsfileutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsfileutils.cpp
3  ---------------------
4  begin : November 2017
5  copyright : (C) 2017 by Etienne Trimaille
6  email : etienne.trimaille at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 #include "qgsfileutils.h"
16 #include <QObject>
17 #include <QRegularExpression>
18 #include <QFileInfo>
19 #include <QDir>
20 #include <QSet>
21 
22 QString QgsFileUtils::representFileSize( qint64 bytes )
23 {
24  QStringList list;
25  list << QObject::tr( "KB" ) << QObject::tr( "MB" ) << QObject::tr( "GB" ) << QObject::tr( "TB" );
26 
27  QStringListIterator i( list );
28  QString unit = QObject::tr( "bytes" );
29 
30  while ( bytes >= 1024.0 && i.hasNext() )
31  {
32  unit = i.next();
33  bytes /= 1024.0;
34  }
35  return QStringLiteral( "%1 %2" ).arg( QString::number( bytes ), unit );
36 }
37 
38 QStringList QgsFileUtils::extensionsFromFilter( const QString &filter )
39 {
40  const QRegularExpression rx( QStringLiteral( "\\*\\.([a-zA-Z0-9]+)" ) );
41  QStringList extensions;
42  QRegularExpressionMatchIterator matches = rx.globalMatch( filter );
43 
44  while ( matches.hasNext() )
45  {
46  const QRegularExpressionMatch match = matches.next();
47  if ( match.hasMatch() )
48  {
49  QStringList newExtensions = match.capturedTexts();
50  newExtensions.pop_front(); // remove whole match
51  extensions.append( newExtensions );
52  }
53  }
54  return extensions;
55 }
56 
57 QString QgsFileUtils::ensureFileNameHasExtension( const QString &f, const QStringList &extensions )
58 {
59  if ( extensions.empty() || f.isEmpty() )
60  return f;
61 
62  QString fileName = f;
63  bool hasExt = false;
64  for ( const QString &extension : qgis::as_const( extensions ) )
65  {
66  const QString extWithDot = extension.startsWith( '.' ) ? extension : '.' + extension;
67  if ( fileName.endsWith( extWithDot, Qt::CaseInsensitive ) )
68  {
69  hasExt = true;
70  break;
71  }
72  }
73 
74  if ( !hasExt )
75  {
76  const QString extension = extensions.at( 0 );
77  const QString extWithDot = extension.startsWith( '.' ) ? extension : '.' + extension;
78  fileName += extWithDot;
79  }
80 
81  return fileName;
82 }
83 
84 QString QgsFileUtils::addExtensionFromFilter( const QString &fileName, const QString &filter )
85 {
86  const QStringList extensions = extensionsFromFilter( filter );
87  return ensureFileNameHasExtension( fileName, extensions );
88 }
89 
90 QString QgsFileUtils::stringToSafeFilename( const QString &string )
91 {
92  QRegularExpression rx( QStringLiteral( "[/\\\\\\?%\\*\\:\\|\"<>]" ) );
93  QString s = string;
94  s.replace( rx, QStringLiteral( "_" ) );
95  return s;
96 }
97 
98 QString QgsFileUtils::findClosestExistingPath( const QString &path )
99 {
100  if ( path.isEmpty() )
101  return QString();
102 
103  QDir currentPath;
104  QFileInfo fi( path );
105  if ( fi.isFile() )
106  currentPath = fi.dir();
107  else
108  currentPath = QDir( path );
109 
110  QSet< QString > visited;
111  while ( !currentPath.exists() )
112  {
113  const QString parentPath = QDir::cleanPath( currentPath.absolutePath() + QStringLiteral( "/.." ) );
114  if ( visited.contains( parentPath ) )
115  return QString(); // break circular links
116 
117  if ( parentPath.isEmpty() || parentPath == QStringLiteral( "." ) )
118  return QString();
119  currentPath = QDir( parentPath );
120  visited << parentPath;
121  }
122 
123  const QString res = QDir::cleanPath( currentPath.absolutePath() );
124 
125  if ( res == QDir::currentPath() )
126  return QString(); // avoid default to binary folder if a filename alone is specified
127 
128  return res == QStringLiteral( "." ) ? QString() : res;
129 }
static QString findClosestExistingPath(const QString &path)
Returns the top-most existing folder from path.
static QString ensureFileNameHasExtension(const QString &fileName, const QStringList &extensions)
Ensures that a fileName ends with an extension from the provided list of extensions.
static QString representFileSize(qint64 bytes)
Returns the human size from bytes.
static QString stringToSafeFilename(const QString &string)
Converts a string to a safe filename, replacing characters which are not safe for filenames with an &#39;...
static QStringList extensionsFromFilter(const QString &filter)
Returns a list of the extensions contained within a file filter string.
static QString addExtensionFromFilter(const QString &fileName, const QString &filter)
Ensures that a fileName ends with an extension from the specified filter string.