diff --git a/include/eepp/core/string.hpp b/include/eepp/core/string.hpp
index 1595781b8..9ab249c4c 100644
--- a/include/eepp/core/string.hpp
+++ b/include/eepp/core/string.hpp
@@ -541,7 +541,7 @@ class EE_API String {
/** glob matches a string against a glob
** @return True if matches
*/
- static bool globMatch( const std::string_view& text, const std::string_view& glob,
+ static bool globMatch( std::string_view text, std::string_view glob,
bool caseInsensitive = false );
/** glob matches a string against a set of globs
diff --git a/src/eepp/core/string.cpp b/src/eepp/core/string.cpp
index eb93d2d04..794114636 100644
--- a/src/eepp/core/string.cpp
+++ b/src/eepp/core/string.cpp
@@ -227,8 +227,7 @@ const std::size_t String::InvalidPos = StringType::npos;
#define PATHSEP '/'
#define CASE( c, caseInsensitive ) ( caseInsensitive ? std::tolower( c ) : ( c ) )
-bool String::globMatch( const std::string_view& text, const std::string_view& glob,
- bool caseInsensitive ) {
+bool String::globMatch( std::string_view text, std::string_view glob, bool caseInsensitive ) {
size_t i = 0;
size_t j = 0;
size_t n = text.size();
diff --git a/src/tools/ecode/applayout.xml.hpp b/src/tools/ecode/applayout.xml.hpp
index 26ac77ac9..3a2a5f14f 100644
--- a/src/tools/ecode/applayout.xml.hpp
+++ b/src/tools/ecode/applayout.xml.hpp
@@ -551,9 +551,6 @@ R"html(
-
-
@@ -643,4 +640,7 @@ R"html(
tooltip='@string(menu_hold_shift_hint_desc, "Keeping \"Shift\" clicked while changing any options it will keep the menu open.")' />
+
+
)html"
diff --git a/src/tools/ecode/globalsearchcontroller.cpp b/src/tools/ecode/globalsearchcontroller.cpp
index fc23745a4..1fd2e0027 100644
--- a/src/tools/ecode/globalsearchcontroller.cpp
+++ b/src/tools/ecode/globalsearchcontroller.cpp
@@ -593,7 +593,7 @@ void GlobalSearchController::showGlobalSearch( bool searchReplace ) {
mGlobalSearchInput->setText( text );
}
mGlobalSearchInput->getDocument().selectAll();
- auto* loader = mGlobalSearchTree->getParent()->find( "loader" );
+ auto* loader = mGlobalSearchLayout->getParent()->find( "loader" );
if ( loader )
loader->setVisible( true );
if ( !searchReplace ) {
@@ -671,10 +671,16 @@ void GlobalSearchController::updateGlobalSearchBar() {
void GlobalSearchController::hideGlobalSearchBar() {
mGlobalSearchBarLayout->setEnabled( false )->setVisible( false );
mGlobalSearchLayout->setVisible( false );
- auto* loader = mGlobalSearchTree->getParent()->find( "loader" );
- if ( loader )
+ auto* loader = mGlobalSearchLayout->getParent()->find( "loader" );
+ if ( loader ) {
loader->setVisible( false );
+ loader->close();
+ }
mApp->getStatusBar()->updateState();
+ if ( mCurSearch ) {
+ mCurSearch->active = false;
+ mApp->getThreadPool()->removeWithTag( mCurSearch->taskTag );
+ }
}
void GlobalSearchController::toggleGlobalSearchBar() {
@@ -762,67 +768,78 @@ void GlobalSearchController::doGlobalSearch( String text, String filter, bool ca
TextDocument::FindReplaceType searchType,
bool escapeSequence, bool searchReplace,
bool searchAgain ) {
- if ( mApp->getDirTree() && mApp->getDirTree()->getFilesCount() > 0 && !text.empty() ) {
- mGlobalSearchTree = searchReplace ? mGlobalSearchTreeReplace : mGlobalSearchTreeSearch;
- mGlobalSearchTreeSearch->setVisible( !searchReplace );
- mGlobalSearchTreeReplace->setVisible( searchReplace );
- mGlobalSearchLayout->findByClass( "status_box" )->setVisible( true );
- mGlobalSearchLayout->findByClass( "replace_box" )->setVisible( false );
- mGlobalSearchLayout->findByClass( "search_str" )->setText( text );
- UILoader* loader = UILoader::New();
- loader->setId( "loader" );
- loader->setRadius( 48 );
- loader->setOutlineThickness( 6 );
- loader->setParent( mGlobalSearchLayout->getParent() );
- loader->setPosition( mGlobalSearchLayout->getPosition() +
- mGlobalSearchLayout->getSize() * 0.5f - loader->getSize() * 0.5f );
- Clock clock;
- if ( escapeSequence )
- text.unescape();
- std::string search( text.toUtf8() );
+ if ( nullptr == mApp->getDirTree() || !mApp->getDirTree()->isReady() ) {
+ mApp->getNotificationCenter()->addNotification( mApp->i18n(
+ "project_still_indexing", "Project is still being indexed, please wait a moment." ) );
+ return;
+ }
- std::vector> openDocs;
- mSplitter->forEachDocSharedPtr(
- [&openDocs]( auto doc ) { openDocs.emplace_back( std::move( doc ) ); } );
- auto filters = parseGlobMatches( filter );
- auto imageExts = Image::getImageExtensionsSupported();
- imageExts.erase( std::remove_if( imageExts.begin(), imageExts.end(),
- []( const std::string& ext ) { return ext == "svg"; } ),
- imageExts.end() );
- filters.reserve( filters.size() + imageExts.size() );
- for ( const auto& ext : imageExts ) {
- // If user explicitly requested to filter some extension, respect it and do not add the
- // ignore for it.
- std::string extGlob( "*." + ext );
- if ( std::find_if( filters.begin(), filters.end(),
- [&extGlob]( const std::pair& filter ) {
- return filter.first == extGlob;
- } ) != filters.end() )
- continue;
- filters.emplace_back( extGlob, true );
- }
+ if ( mApp->getDirTree()->getFilesCount() == 0 || text.empty() ) {
+ return;
+ }
- ProjectSearch::find(
- mApp->getDirTree()->getFiles(), search, mApp->getThreadPool(),
- [this, clock, search, loader, searchReplace, searchAgain, escapeSequence, searchType,
- filter]( const ProjectSearch::ConsolidatedResult& res ) {
- Log::info( "Global search for \"%s\" took %s", search.c_str(),
- clock.getElapsedTime().toString() );
- mUISceneNode->runOnMainThread( [this, loader, res = std::move( res ), search,
- searchReplace, searchAgain, escapeSequence,
- searchType, filter] {
- mLastSearchConfig = std::move( res.first );
- auto model = ProjectSearch::asModel( res.second );
- model->setOpType( searchType );
- updateGlobalSearchHistory( model, search, filter, searchReplace, searchAgain,
- escapeSequence );
- updateGlobalSearchBarResults( search, model, searchReplace, escapeSequence );
+ mGlobalSearchTree = searchReplace ? mGlobalSearchTreeReplace : mGlobalSearchTreeSearch;
+ mGlobalSearchTreeSearch->setVisible( !searchReplace );
+ mGlobalSearchTreeReplace->setVisible( searchReplace );
+ mGlobalSearchLayout->findByClass( "status_box" )->setVisible( true );
+ mGlobalSearchLayout->findByClass( "replace_box" )->setVisible( false );
+ mGlobalSearchLayout->findByClass( "search_str" )->setText( text );
+ UILoader* loader = UILoader::New();
+ loader->setId( "loader" );
+ loader->setRadius( 48 );
+ loader->setOutlineThickness( 6 );
+ loader->setParent( mGlobalSearchLayout->getParent() );
+ loader->setPosition( mGlobalSearchLayout->getPosition() +
+ mGlobalSearchLayout->getSize() * 0.5f - loader->getSize() * 0.5f );
+ Clock clock;
+ if ( escapeSequence )
+ text.unescape();
+ std::string search( text.toUtf8() );
+
+ std::vector> openDocs;
+ mSplitter->forEachDocSharedPtr(
+ [&openDocs]( auto doc ) { openDocs.emplace_back( std::move( doc ) ); } );
+ auto filters = parseGlobMatches( filter );
+ auto imageExts = Image::getImageExtensionsSupported();
+ imageExts.erase( std::remove_if( imageExts.begin(), imageExts.end(),
+ []( const std::string& ext ) { return ext == "svg"; } ),
+ imageExts.end() );
+ filters.reserve( filters.size() + imageExts.size() );
+ for ( const auto& ext : imageExts ) {
+ // If user explicitly requested to filter some extension, respect it and do not add the
+ // ignore for it.
+ std::string extGlob( "*." + ext );
+ if ( std::find_if( filters.begin(), filters.end(),
+ [&extGlob]( const std::pair& filter ) {
+ return filter.first == extGlob;
+ } ) != filters.end() )
+ continue;
+ filters.emplace_back( extGlob, true );
+ }
+
+ mCurSearch = ProjectSearch::find(
+ mApp->getDirTree()->getFiles(), search, mApp->getThreadPool(),
+ [this, clock, search, searchReplace, searchAgain, escapeSequence, searchType,
+ filter]( const ProjectSearch::ConsolidatedResult& res ) {
+ Log::info( "Global search for \"%s\" took %s", search.c_str(),
+ clock.getElapsedTime().toString() );
+ mUISceneNode->runOnMainThread( [this, res = std::move( res ), search, searchReplace,
+ searchAgain, escapeSequence, searchType, filter] {
+ mLastSearchConfig = std::move( res.first );
+ auto model = ProjectSearch::asModel( res.second );
+ model->setOpType( searchType );
+ updateGlobalSearchHistory( model, search, filter, searchReplace, searchAgain,
+ escapeSequence );
+ updateGlobalSearchBarResults( search, model, searchReplace, escapeSequence );
+ auto* loader = mGlobalSearchLayout->getParent()->find( "loader" );
+ if ( loader ) {
loader->setVisible( false );
loader->close();
- } );
- },
- caseSensitive, wholeWord, searchType, filters, mApp->getCurrentProject(), openDocs );
- }
+ }
+ mCurSearch = nullptr;
+ } );
+ },
+ caseSensitive, wholeWord, searchType, filters, mApp->getCurrentProject(), openDocs );
}
void GlobalSearchController::onLoadDone( const Variant& lineNum, const Variant& colNum ) {
diff --git a/src/tools/ecode/globalsearchcontroller.hpp b/src/tools/ecode/globalsearchcontroller.hpp
index 6dd6e0023..25314521f 100644
--- a/src/tools/ecode/globalsearchcontroller.hpp
+++ b/src/tools/ecode/globalsearchcontroller.hpp
@@ -87,6 +87,7 @@ class GlobalSearchController {
std::deque mGlobalSearchHistory;
bool mValueChanging{ false };
ProjectSearch::SearchConfig mLastSearchConfig;
+ ProjectSearch::FindData* mCurSearch{ nullptr };
void onLoadDone( const Variant& lineNum, const Variant& colNum );
diff --git a/src/tools/ecode/ignorematcher.cpp b/src/tools/ecode/ignorematcher.cpp
index c08e6144f..27e9a44d1 100644
--- a/src/tools/ecode/ignorematcher.cpp
+++ b/src/tools/ecode/ignorematcher.cpp
@@ -57,7 +57,7 @@ bool GitIgnoreMatcher::parse() {
return !mPatterns.empty();
}
-bool GitIgnoreMatcher::match( const std::string& value ) const {
+bool GitIgnoreMatcher::match( std::string_view value ) const {
if ( mPatterns.empty() )
return false;
bool match = false;
diff --git a/src/tools/ecode/ignorematcher.hpp b/src/tools/ecode/ignorematcher.hpp
index 1c3d9ef30..a150bf650 100644
--- a/src/tools/ecode/ignorematcher.hpp
+++ b/src/tools/ecode/ignorematcher.hpp
@@ -18,7 +18,7 @@ class IgnoreMatcher {
virtual bool canMatch() = 0;
- virtual bool match( const std::string& value ) const = 0;
+ virtual bool match( std::string_view value ) const = 0;
virtual std::string findRepositoryRootPath() const = 0;
@@ -47,7 +47,7 @@ class GitIgnoreMatcher : public IgnoreMatcher {
const std::string& getIgnoreFilePath() const override;
- bool match( const std::string& value ) const override;
+ bool match( std::string_view value ) const override;
std::string findRepositoryRootPath() const override;
diff --git a/src/tools/ecode/notificationcenter.cpp b/src/tools/ecode/notificationcenter.cpp
index 6c6eb1b24..6ef6669ae 100644
--- a/src/tools/ecode/notificationcenter.cpp
+++ b/src/tools/ecode/notificationcenter.cpp
@@ -45,6 +45,7 @@ void NotificationCenter::addNotification( const String& text, const Time& delay,
tv->setText( text );
tv->addClass( "notification" );
tv->setTextSelection( allowCopy );
+ mLayout->toFront();
Action* sequence = Actions::Sequence::New(
{ Actions::FadeIn::New( Seconds( 0.125 ) ), Actions::Delay::New( delay ),
Actions::FadeOut::New( Seconds( 0.125 ) ), Actions::Close::New() } );
@@ -81,6 +82,7 @@ void NotificationCenter::addShowRequest( const String& uri, const String& action
Action* sequence = Actions::Sequence::New(
{ Actions::FadeIn::New( Seconds( 0.125 ) ), Actions::Delay::New( delay ),
Actions::FadeOut::New( Seconds( 0.125 ) ), Actions::Close::New() } );
+ mLayout->toFront();
lay->runAction( sequence );
};
@@ -114,14 +116,14 @@ void NotificationCenter::addInteractiveNotification( String text, String actionT
} );
UIPushButton* pb = lay->findByType( UI_TYPE_PUSHBUTTON )->asType();
pb->setText( actionText );
- pb->onClick(
- [actionText, onInteraction = std::move( onInteraction )]( const MouseEvent* event ) {
- if ( onInteraction )
- onInteraction();
- } );
+ pb->onClick( [actionText, onInteraction = std::move( onInteraction )]( const MouseEvent* ) {
+ if ( onInteraction )
+ onInteraction();
+ } );
Action* sequence = Actions::Sequence::New(
{ Actions::FadeIn::New( Seconds( 0.125 ) ), Actions::Delay::New( delay ),
Actions::FadeOut::New( Seconds( 0.125 ) ), Actions::Close::New() } );
+ mLayout->toFront();
lay->runAction( sequence );
};
diff --git a/src/tools/ecode/projectdirectorytree.cpp b/src/tools/ecode/projectdirectorytree.cpp
index 17d04363c..04c01e00f 100644
--- a/src/tools/ecode/projectdirectorytree.cpp
+++ b/src/tools/ecode/projectdirectorytree.cpp
@@ -80,6 +80,18 @@ void ProjectDirectoryTree::scan( const ProjectDirectoryTree::ScanCompleteEvent&
break;
}
}
+ if ( !found && mAllowedMatcher ) {
+ std::string_view file{ files[i] };
+ if ( String::startsWith( file, mAllowedMatcher->getPath() ) ) {
+ std::string_view localPath( std::string_view{ file }.substr(
+ mAllowedMatcher->getPath().size() ) );
+ if ( mAllowedMatcher->match( localPath ) ) {
+ found = true;
+ }
+ } else if ( mAllowedMatcher->match( file ) ) {
+ found = true;
+ }
+ }
if ( found ) {
mFiles.emplace_back( std::move( files[i] ) );
mNames.emplace_back( std::move( names[i] ) );
@@ -339,16 +351,18 @@ void ProjectDirectoryTree::getDirectoryFiles(
if ( ignoreMatcher.foundMatch() && ignoreMatcher.match( directory, file ) ) {
if ( !allowedMatcher || !allowedMatcher->hasPatterns() )
continue;
- std::string localPath;
+ std::string_view localPath( fullpath );
if ( String::startsWith( directory, allowedMatcher->getPath() ) )
- localPath = directory.substr( allowedMatcher->getPath().size() );
- if ( !allowedMatcher->match( localPath + file ) )
+ localPath = std::string_view{ fullpath }.substr( allowedMatcher->getPath().size() );
+ if ( !allowedMatcher->match( localPath ) )
continue;
} else if ( disallowedMatcher && disallowedMatcher->hasPatterns() ) {
- std::string localPath;
- if ( String::startsWith( directory, disallowedMatcher->getPath() ) )
- localPath = directory.substr( disallowedMatcher->getPath().size() );
- if ( disallowedMatcher->match( localPath + file ) )
+ std::string_view localPath( fullpath );
+ if ( String::startsWith( directory, disallowedMatcher->getPath() ) ) {
+ localPath =
+ std::string_view{ fullpath }.substr( disallowedMatcher->getPath().size() );
+ }
+ if ( disallowedMatcher->match( localPath ) )
continue;
}
diff --git a/src/tools/ecode/projectdirectorytree.hpp b/src/tools/ecode/projectdirectorytree.hpp
index f6ab7c9d3..56a8acf9c 100644
--- a/src/tools/ecode/projectdirectorytree.hpp
+++ b/src/tools/ecode/projectdirectorytree.hpp
@@ -167,6 +167,8 @@ class ProjectDirectoryTree {
bool isRunning() const { return mRunning; }
+ bool isReady() const { return mIsReady; }
+
protected:
std::string mPath;
std::shared_ptr mPool;
diff --git a/src/tools/ecode/projectsearch.cpp b/src/tools/ecode/projectsearch.cpp
index b0bacb339..a390b8668 100644
--- a/src/tools/ecode/projectsearch.cpp
+++ b/src/tools/ecode/projectsearch.cpp
@@ -159,13 +159,6 @@ static std::vector searchInFileRegEx( const s
return searchInFilePatternMatch( file, pattern, caseSensitive, wholeWord );
}
-struct FindData {
- Mutex resMutex;
- Mutex countMutex;
- int resCount{ 0 };
- ProjectSearch::Result res;
-};
-
std::vector
ProjectSearch::fileResFromDoc( const std::string& string, bool caseSensitive, bool wholeWord,
TextDocument::FindReplaceType type,
@@ -192,20 +185,29 @@ ProjectSearch::fileResFromDoc( const std::string& string, bool caseSensitive, bo
return fileRes;
}
-void ProjectSearch::find( const std::vector files, std::string string,
- std::shared_ptr pool, ResultCb result, bool caseSensitive,
- bool wholeWord, const TextDocument::FindReplaceType& type,
- const std::vector& pathFilters, std::string basePath,
- std::vector> openDocs ) {
- if ( files.empty() )
+ProjectSearch::FindData*
+ProjectSearch::find( const std::vector files, std::string string,
+ std::shared_ptr pool, ResultCb result, bool caseSensitive,
+ bool wholeWord, const TextDocument::FindReplaceType& type,
+ const std::vector& pathFilters, std::string basePath,
+ std::vector> openDocs ) {
+ static const std::string_view PROJECT_SEARCH_TASK_TAG = "ProjectSearchFindTag";
+ static const Uint64 PROJECT_SEARCH_TASK_TAG_HASH =
+ std::hash()( PROJECT_SEARCH_TASK_TAG );
+
+ if ( files.empty() ) {
result( {} );
+ return nullptr;
+ }
+ FindData* findData = eeNew( FindData, () );
+ findData->taskTag = PROJECT_SEARCH_TASK_TAG_HASH;
+
FileSystem::dirAddSlashAtEnd( basePath );
- pool->run( [files = std::move( files ), string = std::move( string ), pool = std::move( pool ),
- result = std::move( result ), caseSensitive, wholeWord, type,
- pathFilters = std::move( pathFilters ), basePath = std::move( basePath ),
+ pool->run( [findData, files = std::move( files ), string = std::move( string ),
+ pool = std::move( pool ), result = std::move( result ), caseSensitive, wholeWord,
+ type, pathFilters = std::move( pathFilters ), basePath = std::move( basePath ),
openDocs = std::move( openDocs )]() mutable {
SearchConfig searchConfig( string, caseSensitive, wholeWord, type );
- FindData* findData = eeNew( FindData, () );
findData->resCount = files.size();
if ( !caseSensitive )
String::toLowerInPlace( string );
@@ -244,6 +246,12 @@ void ProjectSearch::find( const std::vector files, std::string stri
}
}
+ if ( !findData->active ) {
+ result( {} );
+ eeDelete( findData );
+ return;
+ }
+
if ( skip ) {
search[pos++] = false;
continue;
@@ -255,7 +263,7 @@ void ProjectSearch::find( const std::vector files, std::string stri
findData->resCount = count;
- if ( count == 0 ) {
+ if ( count == 0 || !findData->active ) {
result( { searchConfig, findData->res } );
eeDelete( findData );
return;
@@ -310,7 +318,7 @@ void ProjectSearch::find( const std::vector files, std::string stri
doc );
}
},
- onSearchEnd );
+ onSearchEnd, PROJECT_SEARCH_TASK_TAG_HASH );
} else {
pool->run(
[findData, file, string, caseSensitive, wholeWord, occ, type]() mutable {
@@ -327,10 +335,11 @@ void ProjectSearch::find( const std::vector files, std::string stri
findData->res.emplace_back( std::string( file ), std::move( fileRes ) );
}
},
- onSearchEnd );
+ onSearchEnd, PROJECT_SEARCH_TASK_TAG_HASH );
}
}
} );
+ return findData;
}
void ProjectSearch::ResultModel::removeLastNewLineCharacter() {
diff --git a/src/tools/ecode/projectsearch.hpp b/src/tools/ecode/projectsearch.hpp
index 04b116b3e..cce6a14ee 100644
--- a/src/tools/ecode/projectsearch.hpp
+++ b/src/tools/ecode/projectsearch.hpp
@@ -243,7 +243,16 @@ class ProjectSearch {
fileResFromDoc( const std::string& string, bool caseSensitive, bool wholeWord,
TextDocument::FindReplaceType type, std::shared_ptr doc );
- static void
+ struct FindData {
+ Mutex resMutex;
+ Mutex countMutex;
+ int resCount{ 0 };
+ ProjectSearch::Result res;
+ bool active{ true };
+ Uint64 taskTag{ 0 };
+ };
+
+ static FindData*
find( const std::vector files, std::string string,
std::shared_ptr pool, ResultCb result, bool caseSensitive,
bool wholeWord = false,