#12663 Add file search tools and updates ensemble import

Introduces a new set of tools for searching files and directories recursively.

Update the ensemble import functionality to use the new file search tools.

Mark the old file system search function as obsolete.
This commit is contained in:
Magne Sjaastad
2025-07-24 15:18:14 +02:00
parent 15ce1f75aa
commit de35c760c0
8 changed files with 219 additions and 93 deletions
@@ -23,6 +23,7 @@ set(SOURCE_GROUP_HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/RiaRegressionTestRunner.h
${CMAKE_CURRENT_LIST_DIR}/RiaExtractionTools.h
${CMAKE_CURRENT_LIST_DIR}/RiaFilePathTools.h
${CMAKE_CURRENT_LIST_DIR}/RiaFileSearchTools.h
${CMAKE_CURRENT_LIST_DIR}/RiaCurveMerger.h
${CMAKE_CURRENT_LIST_DIR}/RiaCurveMerger.inl
${CMAKE_CURRENT_LIST_DIR}/RiaCurveDataTools.h
@@ -82,6 +83,7 @@ set(SOURCE_GROUP_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/RiaRegressionTestRunner.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaExtractionTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaFilePathTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaFileSearchTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaCurveMerger.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaCurveDataTools.cpp
${CMAKE_CURRENT_LIST_DIR}/RiaWellLogCurveMerger.cpp
@@ -18,6 +18,7 @@
#include "RiaEnsembleImportTools.h"
#include "RiaFileSearchTools.h"
#include "RiaGuiApplication.h"
#include "RiaLogging.h"
#include "RiaStdStringTools.h"
@@ -275,8 +276,12 @@ QStringList getMatchingFiles( const QString& basePath, const QString& regexPatte
//
// The basePath will be traversed recursively to find all files matching the regex pattern
//
//
// MSJ 2025-07-24: !! This function is obsolete and should not be used. Replace with createPathsBySearchingFileSystem !!
//
//--------------------------------------------------------------------------------------------------
QStringList createPathsBySearchingFileSystem( const QString& pathPattern, const QString& placeholderString, const QString& enumerationString )
QStringList
createPathsBySearchingFileSystem_obsolete( const QString& pathPattern, const QString& placeholderString, const QString& enumerationString )
{
auto basePath = pathPattern;
@@ -316,4 +321,44 @@ QStringList createPathsBySearchingFileSystem( const QString& pathPattern, const
return matchingFiles;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QStringList createPathsBySearchingFileSystem( const QString& pathPattern, const QString& extension, const QString& placeholderString )
{
auto firstPlaceholderIndex = pathPattern.indexOf( placeholderString );
if ( firstPlaceholderIndex == -1 ) return {};
auto afterFirstPlaceholder = pathPattern.mid( firstPlaceholderIndex );
auto slashIndex = pathPattern.lastIndexOf( '/', firstPlaceholderIndex );
if ( slashIndex == -1 ) return {};
QString pathFilter;
auto lastSlashIndex = afterFirstPlaceholder.lastIndexOf( '/' );
if ( lastSlashIndex != -1 )
{
pathFilter = afterFirstPlaceholder.left( lastSlashIndex + 1 );
}
pathFilter += "*";
QString basePath = pathPattern.left( slashIndex + 1 );
QStringList folders;
RiaFileSearchTools::findMatchingFoldersRecursively( basePath, pathFilter, folders );
QStringList fileFilters;
if ( extension.startsWith( '*' ) )
{
fileFilters.push_back( extension );
}
else
{
fileFilters.push_back( "*" + extension );
}
return RiaFileSearchTools::findFilesInFolders( folders, fileFilters );
}
} // namespace RiaEnsembleImportTools
@@ -38,7 +38,10 @@ std::vector<RimSummaryCase*> createSummaryCasesFromFiles( const QStringList& fil
std::pair<QString, QString> findPathPattern( const QStringList& filePaths, const QString& placeholderString );
QStringList createPathsFromPattern( const QString& basePath, const QString& numberRange, const QString& placeholderString );
QStringList createPathsBySearchingFileSystem( const QString& pathPattern, const QString& placeholderString, const QString& enumerationString );
QStringList createPathsBySearchingFileSystem_obsolete( const QString& pathPattern,
const QString& placeholderString,
const QString& enumerationString );
QStringList createPathsBySearchingFileSystem( const QString& pathPattern, const QString& extension, const QString& placeholderString );
QStringList getMatchingFiles( const QString& basePath, const QString& regexPattern );
} // namespace RiaEnsembleImportTools
@@ -0,0 +1,102 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2025 Equinor ASA
//
// ResInsight 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 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "RiaFileSearchTools.h"
#include "RiaFilePathTools.h"
#include <QDir>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QStringList RiaFileSearchTools::findFilesInFolders( const QStringList& folders,
const QStringList& fileFilters,
const std::function<bool( const QString& )>& callback )
{
QStringList allFiles;
for ( const auto& folder : folders )
{
QDir qdir( folder );
QStringList files = qdir.entryList( fileFilters, QDir::Files );
if ( callback && !callback( qdir.absolutePath() ) )
{
return allFiles;
}
for ( const auto& file : files )
{
QString absFilePath = qdir.absoluteFilePath( file );
allFiles.append( absFilePath );
}
}
return allFiles;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaFileSearchTools::findMatchingFoldersRecursively( const QString& currentDir,
const QString& folderFilter,
QStringList& matchingFolders,
const std::function<bool( const QString& )>& callback )
{
if ( callback && !callback( currentDir ) )
{
return;
}
QStringList pathFilterPartList;
if ( folderFilter.isEmpty() )
{
pathFilterPartList.push_back( "*" );
}
else
{
pathFilterPartList = folderFilter.split( RiaFilePathTools::separator() );
}
QDir qdir( currentDir, pathFilterPartList[0], QDir::NoSort, QDir::Dirs | QDir::NoDotAndDotDot );
QStringList subDirs = qdir.entryList();
if ( pathFilterPartList.size() == 1 && pathFilterPartList[0] == "*" )
{
matchingFolders.push_back( currentDir );
}
for ( const QString& subDir : subDirs )
{
QString fullPath = qdir.absoluteFilePath( subDir );
QString nextPathFilter;
if ( pathFilterPartList.size() == 1 && pathFilterPartList[0] == "*" )
{
nextPathFilter = "*";
}
else
{
auto nextFilterList = pathFilterPartList;
nextFilterList.removeFirst();
nextPathFilter = nextFilterList.join( RiaFilePathTools::separator() );
}
findMatchingFoldersRecursively( fullPath, nextPathFilter, matchingFolders, callback );
}
}
@@ -0,0 +1,37 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2025 Equinor ASA
//
// ResInsight 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 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <QStringList>
//==================================================================================================
//
//==================================================================================================
namespace RiaFileSearchTools
{
QStringList findFilesInFolders( const QStringList& folders,
const QStringList& fileFilters,
const std::function<bool( const QString& )>& callback = nullptr );
void findMatchingFoldersRecursively( const QString& currentDir,
const QString& folderFilter,
QStringList& matchingFolders,
const std::function<bool( const QString& )>& callback = nullptr );
}; // namespace RiaFileSearchTools
@@ -20,6 +20,7 @@
#include "RiaEnsembleNameTools.h"
#include "RiaFilePathTools.h"
#include "RiaFileSearchTools.h"
#include "RiaGuiApplication.h"
#include "RiaStdStringTools.h"
#include "RiaStringListSerializer.h"
@@ -717,96 +718,35 @@ QStringList RicRecursiveFileSearchDialog::findMatchingFiles()
{
if ( cleanTextFromPathFilterField().isEmpty() ) return QStringList();
QStringList dirs;
auto updateDirSearchStatus = [&]( const QString& text ) -> bool
{
if ( m_isCancelPressed ) return false;
updateStatus( SEARCHING_FOR_DIRS, text );
QApplication::processEvents();
return true;
};
auto updateFileSearchStatus = [&]( const QString& text ) -> bool
{
if ( m_isCancelPressed ) return false;
updateStatus( SEARCHING_FOR_FILES, text );
QApplication::processEvents();
return true;
};
QString pathFilter = pathFilterWithoutStartSeparator();
QString rootDir = rootDirWithEndSeparator();
if ( rootDir.size() > 1 && rootDir.endsWith( RiaFilePathTools::separator() ) ) rootDir.chop( 1 );
buildDirectoryListRecursiveSimple( rootDir, pathFilter, &dirs );
QStringList matchingFolders;
RiaFileSearchTools::findMatchingFoldersRecursively( rootDir, pathFilter, matchingFolders, updateDirSearchStatus );
if ( m_isCancelPressed ) return {};
return findFilesInDirs( dirs );
}
QStringList fileNameFilters = createFileNameFilterList();
auto files = RiaFileSearchTools::findFilesInFolders( matchingFolders, fileNameFilters, updateFileSearchStatus );
if ( m_isCancelPressed ) return {};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RicRecursiveFileSearchDialog::buildDirectoryListRecursiveSimple( const QString& currentDirFullPathNoEndSeparator,
const QString& currentPathFilterNoEndSeparator,
QStringList* accumulatedDirs )
{
QString currDir = currentDirFullPathNoEndSeparator;
QString pathFilter = currentPathFilterNoEndSeparator;
if ( m_isCancelPressed )
{
accumulatedDirs->clear();
return;
}
updateStatus( SEARCHING_FOR_DIRS, currDir );
QApplication::processEvents();
if ( pathFilter.isEmpty() )
{
accumulatedDirs->push_back( currentDirFullPathNoEndSeparator );
return;
}
QStringList pathFilterPartList = pathFilter.split( RiaFilePathTools::separator() );
QDir qdir( currDir, pathFilterPartList[0], QDir::NoSort, QDir::Dirs | QDir::NoDotAndDotDot );
QStringList subDirs = qdir.entryList();
if ( pathFilterPartList.size() == 1 && pathFilterPartList[0] == "*" )
{
accumulatedDirs->push_back( currDir );
}
for ( const QString& subDir : subDirs )
{
QString fullPath = qdir.absoluteFilePath( subDir );
QString nextPathFilter;
if ( pathFilterPartList.size() == 1 && pathFilterPartList[0] == "*" )
{
nextPathFilter = "*";
}
else
{
auto pf = pathFilterPartList;
pf.removeFirst();
nextPathFilter = pf.join( RiaFilePathTools::separator() );
}
buildDirectoryListRecursiveSimple( fullPath, nextPathFilter, accumulatedDirs );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QStringList RicRecursiveFileSearchDialog::findFilesInDirs( const QStringList& dirs )
{
QStringList allFiles;
QStringList filters = createFileNameFilterList();
for ( const auto& dir : dirs )
{
QDir qdir( dir );
QStringList files = qdir.entryList( filters, QDir::Files );
if ( m_isCancelPressed ) return QStringList();
updateStatus( SEARCHING_FOR_FILES, qdir.absolutePath() );
QApplication::processEvents();
for ( QString file : files )
{
QString absFilePath = qdir.absoluteFilePath( file );
allFiles.append( absFilePath );
}
}
return allFiles;
return files;
}
//--------------------------------------------------------------------------------------------------
@@ -106,9 +106,7 @@ private:
// File search methods
QStringList findMatchingFiles();
void buildDirectoryListRecursiveSimple( const QString& currentDir, const QString& currentPathFilter, QStringList* accumulatedDirs );
QStringList findFilesInDirs( const QStringList& dirs );
QStringList findMatchingFiles();
QStringList createFileNameFilterList();
static QString replaceWithRealizationStar( const QString& text );
@@ -100,14 +100,13 @@ QStringList RimEnsembleFileSet::createPaths( const QString& extension ) const
QStringList paths;
if ( m_groupingMode() == RiaDefines::EnsembleGroupingMode::RESINSIGHT_OPMFLOW_STRUCTURE )
{
paths =
RiaEnsembleImportTools::createPathsBySearchingFileSystem( pathPatternWithExtension, internal::placeholderString(), "run" );
paths = RiaEnsembleImportTools::createPathsBySearchingFileSystem_obsolete( pathPatternWithExtension,
internal::placeholderString(),
"run" );
}
else
{
paths = RiaEnsembleImportTools::createPathsBySearchingFileSystem( pathPatternWithExtension,
internal::placeholderString(),
"realization" );
paths = RiaEnsembleImportTools::createPathsBySearchingFileSystem( m_pathPattern(), extension, internal::placeholderString() );
}
const auto [pattern, range] = RiaEnsembleImportTools::findPathPattern( paths, internal::placeholderString() );
m_realizationNumbersReadFromFiles = range;