Files
eepp/src/tools/codeeditor/projectsearch.hpp
Martín Lucas Golini 375d1e66e8 Added Variant "String" support.
Added panel location configuration (left or right).
Added default key modifier (CTRL on Linux and windows, META on macOS, ALT on Haiku).
Optimized GlobalSearchController.
Allow using $FILENAME in linter warning pattern.
Optimized ProjectSearch.
Added TextDocument delete on close option (default for temporal files downloaded from the Internet).
2022-03-20 15:04:07 -03:00

207 lines
5.6 KiB
C++

#ifndef PROJECTSEARCH_HPP
#define PROJECTSEARCH_HPP
#include <eepp/core/string.hpp>
#include <eepp/system/threadpool.hpp>
#include <eepp/ui/doc/textdocument.hpp>
#include <eepp/ui/models/model.hpp>
#include <functional>
#include <memory>
#include <string>
using namespace EE;
using namespace EE::System;
using namespace EE::UI::Doc;
using namespace EE::UI::Models;
class ProjectSearch {
public:
struct ResultData {
struct Result {
Result( const String& line, const TextRange& pos, Int64 s, Int64 e ) :
line( line ), position( pos ), start( s ), end( e ) {}
String line;
TextRange position;
Int64 start;
Int64 end;
bool selected{ true };
};
std::string file;
std::vector<Result> results;
bool selected{ true };
void setResultsSelected( bool selected ) {
this->selected = selected;
for ( auto& res : results )
res.selected = selected;
}
bool allResultsSelected() {
for ( const auto& res : results ) {
if ( !res.selected )
return false;
}
return true;
}
bool noneResultsSelected() {
for ( const auto& res : results ) {
if ( res.selected )
return false;
}
return true;
}
};
typedef std::vector<ResultData> Result;
typedef std::function<void( const Result& )> ResultCb;
class ResultModel : public Model {
public:
enum Column {
FileOrPosition,
Line,
LineEnd,
ColumnStart,
ColumnEnd,
Selected,
Data,
ChildCount
};
ResultModel( const Result& result ) : mResult( result ) {}
virtual size_t treeColumn() const { return Column::FileOrPosition; }
ModelIndex parentIndex( const ModelIndex& index ) const {
if ( !index.isValid() || index.internalId() == -1 )
return {};
return createIndex( index.internalId(), index.column(), &mResult[index.internalId()],
-1 );
}
ModelIndex index( int row, int column, const ModelIndex& parent ) const {
if ( row < 0 || column < 0 )
return {};
if ( !parent.isValid() )
return createIndex( row, column, &mResult[row], -1 );
if ( parent.internalData() )
return createIndex( row, column, &mResult[parent.row()].results[row],
parent.row() );
return {};
}
size_t rowCount( const ModelIndex& index ) const {
if ( !index.isValid() )
return mResult.size();
if ( index.internalId() == -1 )
return mResult[index.row()].results.size();
return 0;
}
size_t columnCount( const ModelIndex& ) const { return 2; }
std::string columnName( const size_t& colIndex ) const {
return colIndex == 0 ? "File" : "Line";
}
size_t resultCount() {
size_t count = 0;
for ( const auto& res : mResult )
count += res.results.size();
return count;
}
Variant data( const ModelIndex& index, ModelRole role = ModelRole::Display ) const {
static const char* EMPTY = "";
if ( role == ModelRole::Display ) {
if ( index.internalId() == -1 ) {
if ( index.column() == FileOrPosition ) {
return Variant( String::format( "%s (%zu)",
mResult[index.row()].file.c_str(),
mResult[index.row()].results.size() ) );
}
} else {
switch ( index.column() ) {
case FileOrPosition:
return Variant(
String( String::format( "%6lld ", mResult[index.internalId()]
.results[index.row()]
.position.start()
.line() +
1 ) ) +
mResult[index.internalId()].results[index.row()].line );
}
}
} else if ( role == ModelRole::Custom ) {
if ( index.internalId() != -1 ) {
switch ( index.column() ) {
case FileOrPosition:
return Variant( mResult[index.internalId()]
.results[index.row()]
.position.start()
.line() );
case Line:
return Variant(
mResult[index.internalId()].results[index.row()].line.c_str() );
case ColumnStart:
return Variant( mResult[index.internalId()]
.results[index.row()]
.position.start()
.column() );
case ColumnEnd:
return Variant( mResult[index.internalId()]
.results[index.row()]
.position.end()
.column() );
case Selected:
return Variant(
mResult[index.internalId()].results[index.row()].selected );
case Data:
return Variant(
(void*)&mResult[index.internalId()].results[index.row()] );
case ChildCount:
return Variant( (Int64)0 );
}
} else {
switch ( index.column() ) {
case FileOrPosition:
return Variant( mResult[index.row()].file.c_str() );
case Data:
return Variant( (void*)&mResult[index.row()] );
case ChildCount:
return Variant( (Int64)mResult[index.row()].results.size() );
case Selected:
return Variant( (bool)mResult[index.row()].selected );
}
}
}
return Variant( EMPTY );
}
virtual void update() { onModelUpdate(); }
const Result& getResult() const { return mResult; }
protected:
Result mResult;
};
static std::shared_ptr<ResultModel> asModel( const Result& result ) {
return std::make_shared<ResultModel>( result );
}
static void
find( const std::vector<std::string> files, const std::string& string, ResultCb result,
bool caseSensitive, bool wholeWord = false,
const TextDocument::FindReplaceType& type = TextDocument::FindReplaceType::Normal );
static void
find( const std::vector<std::string> files, std::string string,
std::shared_ptr<ThreadPool> pool, ResultCb result, bool caseSensitive,
bool wholeWord = false,
const TextDocument::FindReplaceType& type = TextDocument::FindReplaceType::Normal );
};
#endif // PROJECTSEARCH_HPP