mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-06-04 20:46:29 +03:00
Git status: Detect staged and non-staged for a single file and generate two different statuses.
Generate events for row mouse clicks.
This commit is contained in:
@@ -116,6 +116,11 @@ class EE_API UIAbstractTableView : public UIAbstractView {
|
||||
|
||||
UITableCell* getCellFromIndex( const ModelIndex& index ) const;
|
||||
|
||||
virtual void onOpenModelIndex( const ModelIndex& index, const Event* triggerEvent = nullptr );
|
||||
|
||||
virtual void onOpenMenuModelIndex( const ModelIndex& index,
|
||||
const Event* triggerEvent = nullptr );
|
||||
|
||||
protected:
|
||||
friend class EE::UI::UITableHeaderColumn;
|
||||
|
||||
@@ -185,11 +190,6 @@ class EE_API UIAbstractTableView : public UIAbstractView {
|
||||
|
||||
virtual void onScrollChange();
|
||||
|
||||
virtual void onOpenModelIndex( const ModelIndex& index, const Event* triggerEvent = nullptr );
|
||||
|
||||
virtual void onOpenMenuModelIndex( const ModelIndex& index,
|
||||
const Event* triggerEvent = nullptr );
|
||||
|
||||
virtual void onRowCreated( UITableRow* row );
|
||||
|
||||
virtual void onSortColumn( const size_t& colIndex );
|
||||
|
||||
@@ -29,14 +29,29 @@ class EE_API UITableRow : public UIWidget {
|
||||
|
||||
UITableRow() : UIWidget( "table::row" ) {}
|
||||
|
||||
static Event::EventType isMouseEvent( Uint32 msg ) {
|
||||
switch ( msg ) {
|
||||
case NodeMessage::MouseClick:
|
||||
return Event::MouseClick;
|
||||
case NodeMessage::MouseDoubleClick:
|
||||
return Event::MouseDoubleClick;
|
||||
case NodeMessage::MouseDown:
|
||||
return Event::MouseDown;
|
||||
case NodeMessage::MouseUp:
|
||||
return Event::MouseUp;
|
||||
}
|
||||
return Event::NoEvent;
|
||||
}
|
||||
|
||||
virtual Uint32 onMessage( const NodeMessage* msg ) {
|
||||
EventDispatcher* eventDispatcher = getEventDispatcher();
|
||||
Node* mouseDownNode = eventDispatcher->getMouseDownNode();
|
||||
Node* draggingNode = eventDispatcher->getNodeDragging();
|
||||
if ( msg->getMsg() == NodeMessage::MouseDown &&
|
||||
auto eventType = isMouseEvent( msg->getMsg() );
|
||||
if ( eventType != Event::NoEvent &&
|
||||
( mouseDownNode == nullptr || mouseDownNode == this || isParentOf( mouseDownNode ) ) &&
|
||||
draggingNode == nullptr ) {
|
||||
sendMouseEvent( Event::MouseDown, eventDispatcher->getMousePos(), msg->getFlags() );
|
||||
sendMouseEvent( eventType, eventDispatcher->getMousePos(), msg->getFlags() );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -100,6 +100,8 @@ class EE_API UITreeView : public UIAbstractTableView {
|
||||
|
||||
void updateContentSize();
|
||||
|
||||
virtual void onOpenTreeModelIndex( const ModelIndex& index, bool open );
|
||||
|
||||
protected:
|
||||
enum class IterationDecision {
|
||||
Continue,
|
||||
@@ -145,8 +147,6 @@ class EE_API UITreeView : public UIAbstractTableView {
|
||||
|
||||
virtual Uint32 onKeyDown( const KeyEvent& event );
|
||||
|
||||
virtual void onOpenTreeModelIndex( const ModelIndex& index, bool open );
|
||||
|
||||
virtual void onSortColumn( const size_t& colIndex );
|
||||
|
||||
void setAllExpanded( const ModelIndex& index = {}, bool expanded = true );
|
||||
|
||||
@@ -478,82 +478,21 @@ Git::Status Git::status( bool recurseSubmodules, const std::string& projectDir )
|
||||
static constexpr auto STATUS_CMD = "-c color.status=never status -b -u -s";
|
||||
Status s;
|
||||
std::string buf;
|
||||
if ( EXIT_SUCCESS != git( DIFF_CMD, projectDir, buf ) )
|
||||
return s;
|
||||
|
||||
getSubModules( projectDir );
|
||||
|
||||
LuaPattern subModulePattern( "^Entering '(.*)'" );
|
||||
|
||||
auto parseNumStat = [&s, &buf, &projectDir, this, &subModulePattern]() {
|
||||
LuaPattern pattern( "(%d+)%s+(%d+)%s+(.+)" );
|
||||
std::string subModulePath = "";
|
||||
readAllLines( buf, [&]( const std::string_view& line ) {
|
||||
LuaPattern::Range matches[4];
|
||||
if ( subModulePattern.matches( line.data(), 0, matches, line.size() ) ) {
|
||||
subModulePath = String::trim(
|
||||
line.substr( matches[1].start, matches[1].end - matches[1].start ) );
|
||||
FileSystem::dirAddSlashAtEnd( subModulePath );
|
||||
} else if ( pattern.matches( line.data(), 0, matches, line.size() ) ) {
|
||||
auto inserted = line.substr( matches[1].start, matches[1].end - matches[1].start );
|
||||
auto deleted = line.substr( matches[2].start, matches[2].end - matches[2].start );
|
||||
auto file = line.substr( matches[3].start, matches[3].end - matches[3].start );
|
||||
int inserts;
|
||||
int deletes;
|
||||
if ( String::fromString( inserts, inserted ) &&
|
||||
String::fromString( deletes, deleted ) && ( inserts || deletes ) ) {
|
||||
auto filePath = subModulePath + file;
|
||||
auto repo = repoName( filePath, projectDir );
|
||||
auto repoIt = s.files.find( repo );
|
||||
GitStatusReport status = { GitStatus::NotSet, GitStatusType::Untracked,
|
||||
GitStatusChar::Untracked };
|
||||
if ( repoIt != s.files.end() ) {
|
||||
bool found = false;
|
||||
for ( auto& fileIt : repoIt->second ) {
|
||||
if ( fileIt.file == filePath ) {
|
||||
fileIt.inserts = inserts;
|
||||
fileIt.deletes = deletes;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !found ) {
|
||||
s.files[repo].push_back(
|
||||
{ std::move( filePath ), inserts, deletes, status } );
|
||||
}
|
||||
} else {
|
||||
s.files.insert(
|
||||
{ repo, { { std::move( filePath ), inserts, deletes, status } } } );
|
||||
}
|
||||
s.totalInserts += inserts;
|
||||
s.totalDeletions += deletes;
|
||||
}
|
||||
}
|
||||
} );
|
||||
};
|
||||
|
||||
parseNumStat();
|
||||
|
||||
git( DIFF_STAGED_CMD, projectDir, buf );
|
||||
parseNumStat();
|
||||
|
||||
bool submodules = hasSubmodules( projectDir );
|
||||
|
||||
if ( recurseSubmodules && submodules ) {
|
||||
gitSubmodules( DIFF_CMD, projectDir, buf );
|
||||
parseNumStat();
|
||||
|
||||
gitSubmodules( DIFF_STAGED_CMD, projectDir, buf );
|
||||
parseNumStat();
|
||||
}
|
||||
LuaPattern subModulePattern( "^Entering '(.*)'" );
|
||||
|
||||
bool modifiedSubmodule = false;
|
||||
auto parseStatus = [&s, &buf, &modifiedSubmodule, &projectDir, this, &subModulePattern]() {
|
||||
std::string subModulePath = "";
|
||||
LuaPattern pattern( "^([mMARTUD?%s][mMARTUD?%s])%s(.*)" );
|
||||
size_t changesCount = countLines( buf );
|
||||
|
||||
if ( changesCount > 1000 )
|
||||
return;
|
||||
|
||||
readAllLines( buf, [&]( const std::string_view& line ) {
|
||||
LuaPattern::Range matches[3];
|
||||
if ( subModulePattern.matches( line.data(), 0, matches, line.size() ) ) {
|
||||
@@ -576,11 +515,14 @@ Git::Status Git::status( bool recurseSubmodules, const std::string& projectDir )
|
||||
return;
|
||||
}
|
||||
|
||||
bool isStagedAndModified =
|
||||
status.type == GitStatusType::Staged && statusStr[1] != ' ';
|
||||
|
||||
auto filePath = subModulePath + file;
|
||||
auto repo = repoName( filePath, projectDir );
|
||||
auto repoIt = s.files.find( repo );
|
||||
bool found = false;
|
||||
if ( repoIt != s.files.end() ) {
|
||||
bool found = false;
|
||||
for ( auto& fileIt : repoIt->second ) {
|
||||
if ( fileIt.file == filePath ) {
|
||||
fileIt.report = status;
|
||||
@@ -588,16 +530,23 @@ Git::Status Git::status( bool recurseSubmodules, const std::string& projectDir )
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !found )
|
||||
}
|
||||
if ( !found ) {
|
||||
s.files[repo].push_back( { std::move( filePath ), 0, 0, status } );
|
||||
|
||||
if ( isStagedAndModified ) {
|
||||
status.type = GitStatusType::Changed;
|
||||
|
||||
s.files[repo].push_back( { std::move( filePath ), 0, 0, status } );
|
||||
} else {
|
||||
s.files.insert( { repo, { { std::move( filePath ), 0, 0, status } } } );
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
};
|
||||
|
||||
git( STATUS_CMD, projectDir, buf );
|
||||
if ( EXIT_SUCCESS != git( STATUS_CMD, projectDir, buf ) )
|
||||
return s;
|
||||
|
||||
parseStatus();
|
||||
|
||||
if ( modifiedSubmodule && recurseSubmodules && submodules ) {
|
||||
@@ -605,6 +554,70 @@ Git::Status Git::status( bool recurseSubmodules, const std::string& projectDir )
|
||||
parseStatus();
|
||||
}
|
||||
|
||||
auto parseNumStat = [&s, &buf, &projectDir, this, &subModulePattern]( bool isStaged ) {
|
||||
LuaPattern pattern( "(%d+)%s+(%d+)%s+(.+)" );
|
||||
std::string subModulePath = "";
|
||||
readAllLines( buf, [&]( const std::string_view& line ) {
|
||||
LuaPattern::Range matches[4];
|
||||
if ( subModulePattern.matches( line.data(), 0, matches, line.size() ) ) {
|
||||
subModulePath = String::trim(
|
||||
line.substr( matches[1].start, matches[1].end - matches[1].start ) );
|
||||
FileSystem::dirAddSlashAtEnd( subModulePath );
|
||||
} else if ( pattern.matches( line.data(), 0, matches, line.size() ) ) {
|
||||
auto inserted = line.substr( matches[1].start, matches[1].end - matches[1].start );
|
||||
auto deleted = line.substr( matches[2].start, matches[2].end - matches[2].start );
|
||||
auto file = line.substr( matches[3].start, matches[3].end - matches[3].start );
|
||||
int inserts;
|
||||
int deletes;
|
||||
if ( String::fromString( inserts, inserted ) &&
|
||||
String::fromString( deletes, deleted ) && ( inserts || deletes ) ) {
|
||||
auto filePath = subModulePath + file;
|
||||
auto repo = repoName( filePath, projectDir );
|
||||
auto repoIt = s.files.find( repo );
|
||||
GitStatusReport status = { GitStatus::NotSet, GitStatusType::Untracked,
|
||||
GitStatusChar::Untracked };
|
||||
bool found = false;
|
||||
if ( repoIt != s.files.end() ) {
|
||||
for ( auto& fileIt : repoIt->second ) {
|
||||
if ( fileIt.file == filePath ) {
|
||||
if ( isStaged && fileIt.report.type != Git::GitStatusType::Staged )
|
||||
continue;
|
||||
if ( !isStaged && fileIt.report.type == Git::GitStatusType::Staged )
|
||||
continue;
|
||||
fileIt.inserts = inserts;
|
||||
fileIt.deletes = deletes;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( !found ) {
|
||||
s.files[repo].push_back(
|
||||
{ std::move( filePath ), inserts, deletes, status } );
|
||||
}
|
||||
s.totalInserts += inserts;
|
||||
s.totalDeletions += deletes;
|
||||
}
|
||||
}
|
||||
} );
|
||||
};
|
||||
|
||||
if ( EXIT_SUCCESS != git( DIFF_CMD, projectDir, buf ) )
|
||||
return s;
|
||||
|
||||
parseNumStat( false );
|
||||
|
||||
git( DIFF_STAGED_CMD, projectDir, buf );
|
||||
parseNumStat( true );
|
||||
|
||||
if ( recurseSubmodules && submodules ) {
|
||||
gitSubmodules( DIFF_CMD, projectDir, buf );
|
||||
parseNumStat( false );
|
||||
|
||||
gitSubmodules( DIFF_STAGED_CMD, projectDir, buf );
|
||||
parseNumStat( true );
|
||||
}
|
||||
|
||||
for ( auto& [_, repo] : s.files ) {
|
||||
for ( auto& val : repo ) {
|
||||
if ( val.report.symbol == GitStatusChar::Added && val.inserts == 0 ) {
|
||||
|
||||
@@ -959,6 +959,13 @@ void GitPlugin::buildSidePanelTab() {
|
||||
mStatusTree->setAutoColumnsWidth( true );
|
||||
mStatusTree->setHeadersVisible( false );
|
||||
mStatusTree->setExpandersAsIcons( true );
|
||||
mStatusTree->on( Event::OnRowCreated, [this]( const Event* event ) {
|
||||
UITableRow* row = event->asRowCreatedEvent()->getRow();
|
||||
row->on( Event::MouseUp, [this, row]( const Event* event ) {
|
||||
if ( event->asMouseEvent()->getFlags() & EE_BUTTON_RMASK )
|
||||
mStatusTree->onOpenMenuModelIndex( row->getCurIndex(), event );
|
||||
} );
|
||||
} );
|
||||
mStatusTree->on( Event::OnModelEvent, [this]( const Event* event ) {
|
||||
const ModelEvent* modelEvent = static_cast<const ModelEvent*>( event );
|
||||
if ( modelEvent->getModel() == nullptr )
|
||||
|
||||
Reference in New Issue
Block a user