mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-06-03 03:56:30 +03:00
227 lines
6.4 KiB
C++
227 lines
6.4 KiB
C++
#include "gitstatusmodel.hpp"
|
|
#include "gitplugin.hpp"
|
|
|
|
#include <map>
|
|
#include <set>
|
|
|
|
#include <eepp/system/filesystem.hpp>
|
|
#include <eepp/ui/uiiconthememanager.hpp>
|
|
|
|
namespace ecode {
|
|
|
|
GitStatusModel::GitStatusModel( Git::FilesStatus&& status, GitPlugin* gitPlugin ) :
|
|
mPlugin( gitPlugin ) {
|
|
std::map<std::string, std::set<Git::GitStatusType>> typesFound;
|
|
std::unordered_map<std::string, size_t> repoPos;
|
|
std::unordered_map<size_t, std::unordered_map<Git::GitStatusType, size_t>> repoTypePos;
|
|
|
|
for ( auto& s : status )
|
|
for ( auto& f : s.second )
|
|
typesFound[s.first].insert( f.report.type );
|
|
|
|
for ( const auto& tf : typesFound ) {
|
|
RepoStatus rs;
|
|
rs.repo = tf.first;
|
|
size_t pos = mStatus.size();
|
|
repoPos[rs.repo] = pos;
|
|
for ( const auto& s : tf.second ) {
|
|
RepoStatusType rt;
|
|
rt.typeStr = mPlugin->statusTypeToString( s );
|
|
rt.type = s;
|
|
repoTypePos[pos][s] = rs.type.size();
|
|
rs.type.emplace_back( std::move( rt ) );
|
|
}
|
|
mStatus.emplace_back( std::move( rs ) );
|
|
}
|
|
|
|
for ( auto& s : status ) {
|
|
for ( auto& fv : s.second ) {
|
|
auto pos = repoPos[s.first];
|
|
auto typePos = repoTypePos[pos][fv.report.type];
|
|
DiffFile df( std::move( fv ), &mStatus[pos].type[typePos] );
|
|
mStatus[pos].type[typePos].files.emplace_back( std::move( df ) );
|
|
}
|
|
}
|
|
|
|
// Set the parents after the addresses are stable
|
|
for ( auto& status : mStatus ) {
|
|
for ( auto& type : status.type ) {
|
|
for ( auto& f : type.files )
|
|
f.parent = &type;
|
|
type.parent = &status;
|
|
}
|
|
}
|
|
}
|
|
|
|
size_t GitStatusModel::rowCount( const ModelIndex& index ) const {
|
|
if ( !index.isValid() )
|
|
return mStatus.size();
|
|
|
|
if ( index.internalId() == Repo )
|
|
return mStatus[index.row()].type.size();
|
|
|
|
if ( index.internalId() == Status )
|
|
return mStatus[index.parent().row()].type[index.row()].files.size();
|
|
|
|
return 0;
|
|
}
|
|
|
|
ModelIndex GitStatusModel::parentIndex( const ModelIndex& index ) const {
|
|
if ( !index.isValid() || index.internalId() == Repo )
|
|
return {};
|
|
|
|
if ( index.internalId() == Status ) {
|
|
RepoStatusType* status = reinterpret_cast<RepoStatusType*>( index.internalData() );
|
|
size_t f = 0;
|
|
size_t statusSize = mStatus.size();
|
|
for ( size_t i = 0; i < statusSize; i++ ) {
|
|
if ( &mStatus[i] == status->parent ) {
|
|
f = i;
|
|
break;
|
|
}
|
|
}
|
|
return createIndex( f, index.column(), status->parent, Repo );
|
|
}
|
|
|
|
if ( index.internalId() == GitFile ) {
|
|
DiffFile* file = reinterpret_cast<DiffFile*>( index.internalData() );
|
|
RepoStatusType* status = file->parent;
|
|
RepoStatus* repoStatus = status->parent;
|
|
size_t typeSize = repoStatus->type.size();
|
|
size_t f = 0;
|
|
for ( size_t i = 0; i < typeSize; i++ ) {
|
|
if ( &status->parent->type[i] == status ) {
|
|
f = i;
|
|
break;
|
|
}
|
|
}
|
|
return createIndex( f, index.column(), status, Status );
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
ModelIndex GitStatusModel::index( int row, int column, const ModelIndex& parent ) const {
|
|
if ( row < 0 || column < 0 )
|
|
return {};
|
|
|
|
if ( !parent.isValid() )
|
|
return createIndex( row, column, &mStatus[row], Repo );
|
|
|
|
if ( parent.internalId() == Repo )
|
|
return createIndex( row, column, &mStatus[parent.row()].type[row], Status );
|
|
|
|
if ( parent.internalId() == Status ) {
|
|
size_t pprow = parent.parent().row();
|
|
size_t prow = parent.row();
|
|
return createIndex( row, column, &mStatus[pprow].type[prow].files[row], GitFile );
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
Variant GitStatusModel::data( const ModelIndex& index, ModelRole role ) const {
|
|
switch ( role ) {
|
|
case ModelRole::Display: {
|
|
if ( index.internalId() == Repo ) {
|
|
if ( index.column() == Column::File )
|
|
return Variant( mStatus[index.row()].repo.c_str() );
|
|
return Variant( GIT_EMPTY );
|
|
} else if ( index.internalId() == Status ) {
|
|
if ( index.column() == Column::File ) {
|
|
return Variant(
|
|
mStatus[index.parent().row()].type[index.row()].typeStr.c_str() );
|
|
}
|
|
return Variant( GIT_EMPTY );
|
|
}
|
|
const Git::DiffFile& s = mStatus[index.parent().parent().row()]
|
|
.type[index.parent().row()]
|
|
.files[index.row()];
|
|
switch ( index.column() ) {
|
|
case Column::File:
|
|
return Variant( FileSystem::fileNameFromPath( s.file ) );
|
|
case Column::Inserted:
|
|
return Variant( String::format( "+%d ", s.inserts ) );
|
|
case Column::Removed:
|
|
return Variant( String::format( "-%d ", s.deletes ) );
|
|
case Column::State:
|
|
return Variant( String::format( "%c", s.report.symbol ) );
|
|
case Column::RelativeDirectory:
|
|
return Variant( FileSystem::fileRemoveFileName( s.file ) );
|
|
}
|
|
break;
|
|
}
|
|
case ModelRole::Class: {
|
|
if ( index.internalId() == GitFile ) {
|
|
switch ( index.column() ) {
|
|
case Column::Inserted:
|
|
return Variant( GIT_SUCCESS );
|
|
case Column::Removed:
|
|
return Variant( GIT_ERROR );
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case ModelRole::Icon: {
|
|
if ( (Int64)treeColumn() == index.column() ) {
|
|
if ( index.internalId() == Repo ) {
|
|
return Variant( mPlugin->findIcon( "repo" ) );
|
|
} else if ( index.internalId() == GitFile ) {
|
|
const Git::DiffFile& s = mStatus[index.parent().parent().row()]
|
|
.type[index.parent().row()]
|
|
.files[index.row()];
|
|
std::string iconName = UIIconThemeManager::getIconNameFromFileName( s.file );
|
|
auto* scene = mPlugin->getUISceneNode();
|
|
auto* d = scene->findIcon( iconName );
|
|
if ( !d )
|
|
return scene->findIcon( "file" );
|
|
return d;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return {};
|
|
}
|
|
|
|
const GitStatusModel::RepoStatus* GitStatusModel::repo( const ModelIndex& index ) const {
|
|
if ( index.internalId() != Repo )
|
|
return nullptr;
|
|
return &mStatus[index.row()];
|
|
}
|
|
|
|
const GitStatusModel::RepoStatusType* GitStatusModel::statusType( const ModelIndex& index ) const {
|
|
if ( index.internalId() != Status )
|
|
return nullptr;
|
|
return &mStatus[index.parent().row()].type[index.row()];
|
|
}
|
|
|
|
const GitStatusModel::DiffFile* GitStatusModel::file( const ModelIndex& index ) const {
|
|
if ( index.internalId() != GitFile )
|
|
return nullptr;
|
|
return &mStatus[index.parent().parent().row()].type[index.parent().row()].files[index.row()];
|
|
}
|
|
|
|
std::vector<std::string> GitStatusModel::getFiles( const std::string& repo,
|
|
uint32_t statusType ) const {
|
|
std::vector<std::string> files;
|
|
for ( const auto& status : mStatus ) {
|
|
if ( status.repo == repo ) {
|
|
for ( const auto& type : status.type ) {
|
|
if ( static_cast<uint32_t>( type.type ) & statusType ) {
|
|
for ( const auto& file : type.files )
|
|
files.push_back( file.file );
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return files;
|
|
}
|
|
|
|
} // namespace ecode
|