diff --git a/common/commit.cpp b/common/commit.cpp index 0b9447bd40..016767ea44 100644 --- a/common/commit.cpp +++ b/common/commit.cpp @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2016 CERN + * Copyright 2016-2017 CERN * @author Tomasz Wlostowski * @author Maciej Suminski * @@ -52,7 +52,7 @@ COMMIT& COMMIT::Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType ) { case CHT_ADD: assert( m_changedItems.find( aItem ) == m_changedItems.end() ); - makeEntry( aItem, CHT_ADD | flag ); + makeEntry( aItem, CHT_ADD | flag ); return *this; case CHT_REMOVE: @@ -62,13 +62,7 @@ COMMIT& COMMIT::Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType ) case CHT_MODIFY: { EDA_ITEM* parent = parentObject( aItem ); - - if( m_changedItems.find( parent ) != m_changedItems.end() ) - return *this; // item has been already modified once - - makeEntry( parent, CHT_MODIFY | flag, parent->Clone() ); - - return *this; + return createModified( parent, parent->Clone(), flag ); } default: @@ -79,19 +73,6 @@ COMMIT& COMMIT::Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType ) } -COMMIT& COMMIT::Modified( EDA_ITEM* aItem, EDA_ITEM* aCopy ) -{ - EDA_ITEM* parent = parentObject( aItem ); - - if( m_changedItems.find( parent ) != m_changedItems.end() ) - return *this; // item has been already modified once - - makeEntry( parent, CHT_MODIFY, aCopy ); - - return *this; -} - - COMMIT& COMMIT::Stage( std::vector& container, CHANGE_TYPE aChangeType ) { for( EDA_ITEM* item : container ) @@ -133,6 +114,15 @@ COMMIT& COMMIT::Stage( const PICKED_ITEMS_LIST& aItems, UNDO_REDO_T aModFlag ) return *this; } + +int COMMIT::GetStatus( EDA_ITEM* aItem ) +{ + COMMIT_LINE* entry = findEntry( parentObject( aItem ) ); + + return entry ? entry->m_type : 0; +} + + template void eraseIf( Container& c, F&& f ) { @@ -142,6 +132,28 @@ void eraseIf( Container& c, F&& f ) c.end() ); } + +COMMIT& COMMIT::createModified( EDA_ITEM* aItem, EDA_ITEM* aCopy, int aExtraFlags ) +{ + EDA_ITEM* parent = parentObject( aItem ); + auto entryIt = m_changedItems.find( parent ); + + if( entryIt != m_changedItems.end() ) + { +#ifdef DEBUG + const COMMIT_LINE* entry = findEntry( parent ); + wxASSERT_MSG( entry->m_copy == aCopy, "Staging a different copy, possible memleak" ); +#endif + + return *this; // item has been already modified once + } + + makeEntry( parent, CHT_MODIFY | aExtraFlags, aCopy ); + + return *this; +} + + void COMMIT::makeEntry( EDA_ITEM* aItem, CHANGE_TYPE aType, EDA_ITEM* aCopy ) { // Expect an item copy if it is going to be modified @@ -165,6 +177,18 @@ void COMMIT::makeEntry( EDA_ITEM* aItem, CHANGE_TYPE aType, EDA_ITEM* aCopy ) } +COMMIT::COMMIT_LINE* COMMIT::findEntry( EDA_ITEM* aItem ) +{ + for( COMMIT_LINE& change : m_changes ) + { + if( change.m_item == aItem ) + return &change; + } + + return nullptr; +} + + CHANGE_TYPE COMMIT::convert( UNDO_REDO_T aType ) const { switch( aType ) diff --git a/include/commit.h b/include/commit.h index 62fbf7d98c..d883bba129 100644 --- a/include/commit.h +++ b/include/commit.h @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2016 CERN + * Copyright 2016-2017 CERN * @author Tomasz Wlostowski * @author Maciej Suminski * @@ -107,7 +107,10 @@ public: ///> Creates an undo entry for an item that has been already modified. Requires a copy done ///> before the modification. - COMMIT& Modified( EDA_ITEM* aItem, EDA_ITEM* aCopy ); + COMMIT& Modified( EDA_ITEM* aItem, EDA_ITEM* aCopy ) + { + return createModified( aItem, aCopy ); + } template COMMIT& StageItems( const Range& aRange, CHANGE_TYPE aChangeType ) @@ -137,6 +140,9 @@ public: return m_changes.empty(); } + ///> Returns status of an item. + int GetStatus( EDA_ITEM* aItem ); + protected: struct COMMIT_LINE { @@ -157,8 +163,16 @@ protected: m_changes.clear(); } + COMMIT& createModified( EDA_ITEM* aItem, EDA_ITEM* aCopy, int aExtraFlags = 0 ); + virtual void makeEntry( EDA_ITEM* aItem, CHANGE_TYPE aType, EDA_ITEM* aCopy = NULL ); + /** + * Searches for an entry describing change for a particular item + * @return null if there is no related entry. + */ + COMMIT_LINE* findEntry( EDA_ITEM* aItem ); + virtual EDA_ITEM* parentObject( EDA_ITEM* aItem ) const = 0; CHANGE_TYPE convert( UNDO_REDO_T aType ) const;