7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-20 18:01:41 +00:00

Undo for schematic-wide operations.

Editing value/footprint fields of multi-unit components.
Find/Change.
Annotation.
Back annotation.

Fixes https://gitlab.com/kicad/code/kicad/issues/2122

Fixes https://gitlab.com/kicad/code/kicad/issues/4869

Fixes https://gitlab.com/kicad/code/kicad/issues/3933

Fixes https://gitlab.com/kicad/code/kicad/issues/4871

Fixes https://gitlab.com/kicad/code/kicad/issues/3899
This commit is contained in:
Jeff Young 2020-07-13 12:21:40 +01:00
parent 30eef410a9
commit 7340c97ef9
88 changed files with 768 additions and 881 deletions
common
cvpcb
eeschema
include
pagelayout_editor
pcbnew
qa/qa_utils

View File

@ -36,7 +36,6 @@ wxString BASE_SCREEN::m_PageLayoutDescrFileName; // the name of the page layou
BASE_SCREEN::BASE_SCREEN( EDA_ITEM* aParent, KICAD_T aType ) :
EDA_ITEM( aParent, aType )
{
m_UndoRedoCountMax = DEFAULT_MAX_UNDO_ITEMS;
m_Initialized = false;
m_ScreenNumber = 1;
m_NumberOfScreens = 1; // Hierarchy: Root: ScreenNumber = 1
@ -70,55 +69,6 @@ void BASE_SCREEN::InitDataPoints( const wxSize& aPageSizeIU )
}
void BASE_SCREEN::ClearUndoRedoList()
{
ClearUndoORRedoList( m_UndoList );
ClearUndoORRedoList( m_RedoList );
}
void BASE_SCREEN::PushCommandToUndoList( PICKED_ITEMS_LIST* aNewitem )
{
m_UndoList.PushCommand( aNewitem );
// Delete the extra items, if count max reached
if( m_UndoRedoCountMax > 0 )
{
int extraitems = GetUndoCommandCount() - m_UndoRedoCountMax;
if( extraitems > 0 )
ClearUndoORRedoList( m_UndoList, extraitems );
}
}
void BASE_SCREEN::PushCommandToRedoList( PICKED_ITEMS_LIST* aNewitem )
{
m_RedoList.PushCommand( aNewitem );
// Delete the extra items, if count max reached
if( m_UndoRedoCountMax > 0 )
{
int extraitems = GetRedoCommandCount() - m_UndoRedoCountMax;
if( extraitems > 0 )
ClearUndoORRedoList( m_RedoList, extraitems );
}
}
PICKED_ITEMS_LIST* BASE_SCREEN::PopCommandFromUndoList( )
{
return m_UndoList.PopCommand();
}
PICKED_ITEMS_LIST* BASE_SCREEN::PopCommandFromRedoList( )
{
return m_RedoList.PopCommand();
}
#if defined(DEBUG)
void BASE_SCREEN::Show( int nestLevel, std::ostream& os ) const

View File

@ -81,6 +81,7 @@ EDA_BASE_FRAME::EDA_BASE_FRAME( wxWindow* aParent, FRAME_T aFrameType,
m_hasAutoSave( false ),
m_autoSaveState( false ),
m_autoSaveInterval(-1 ),
m_UndoRedoCountMax( DEFAULT_MAX_UNDO_ITEMS ),
m_userUnits( EDA_UNITS::MILLIMETRES )
{
m_autoSaveTimer = new wxTimer( this, ID_AUTO_SAVE_TIMER );
@ -156,10 +157,10 @@ EDA_BASE_FRAME::~EDA_BASE_FRAME()
delete m_autoSaveTimer;
delete m_fileHistory;
ClearUndoRedoList();
if( SupportsShutdownBlockReason() )
{
RemoveShutdownBlockReason();
}
}
@ -793,6 +794,55 @@ bool EDA_BASE_FRAME::IsContentModified()
}
void EDA_BASE_FRAME::ClearUndoRedoList()
{
ClearUndoORRedoList( m_UndoList );
ClearUndoORRedoList( m_RedoList );
}
void EDA_BASE_FRAME::PushCommandToUndoList( PICKED_ITEMS_LIST* aNewitem )
{
m_UndoList.PushCommand( aNewitem );
// Delete the extra items, if count max reached
if( m_UndoRedoCountMax > 0 )
{
int extraitems = GetUndoCommandCount() - m_UndoRedoCountMax;
if( extraitems > 0 )
ClearUndoORRedoList( m_UndoList, extraitems );
}
}
void EDA_BASE_FRAME::PushCommandToRedoList( PICKED_ITEMS_LIST* aNewitem )
{
m_RedoList.PushCommand( aNewitem );
// Delete the extra items, if count max reached
if( m_UndoRedoCountMax > 0 )
{
int extraitems = GetRedoCommandCount() - m_UndoRedoCountMax;
if( extraitems > 0 )
ClearUndoORRedoList( m_RedoList, extraitems );
}
}
PICKED_ITEMS_LIST* EDA_BASE_FRAME::PopCommandFromUndoList( )
{
return m_UndoList.PopCommand();
}
PICKED_ITEMS_LIST* EDA_BASE_FRAME::PopCommandFromRedoList( )
{
return m_RedoList.PopCommand();
}
void EDA_BASE_FRAME::ChangeUserUnits( EDA_UNITS aUnits )
{
SetUserUnits( aUnits );

View File

@ -570,9 +570,7 @@ void EDA_DRAW_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
aCfg->m_System.units = static_cast<int>( m_userUnits );
aCfg->m_System.first_run_shown = m_firstRunDialogSetting;
if( GetScreen() )
aCfg->m_System.max_undo_items = GetScreen()->GetMaxUndoItems();
aCfg->m_System.max_undo_items = GetMaxUndoItems();
m_galDisplayOptions.WriteConfig( *window );

View File

@ -28,12 +28,34 @@
#include <undo_redo_container.h>
/*
ITEM_PICKER::ITEM_PICKER( EDA_ITEM* aItem, UNDO_REDO_T aUndoRedoStatus )
{
m_undoRedoStatus = aUndoRedoStatus;
SetItem( aItem );
m_pickerFlags = 0;
m_link = nullptr;
m_screen = nullptr;
}
*/
ITEM_PICKER::ITEM_PICKER()
{
m_undoRedoStatus = UR_UNSPECIFIED;
SetItem( nullptr );
m_pickerFlags = 0;
m_link = NULL;
m_screen = nullptr;
}
ITEM_PICKER::ITEM_PICKER( BASE_SCREEN* aScreen, EDA_ITEM* aItem, UNDO_REDO_T aUndoRedoStatus )
{
m_undoRedoStatus = aUndoRedoStatus;
SetItem( aItem );
m_pickerFlags = 0;
m_link = NULL;
m_screen = aScreen;
}
@ -144,6 +166,15 @@ EDA_ITEM* PICKED_ITEMS_LIST::GetPickedItem( unsigned int aIdx ) const
}
BASE_SCREEN* PICKED_ITEMS_LIST::GetScreenForItem( unsigned int aIdx ) const
{
if( aIdx < m_ItemsList.size() )
return m_ItemsList[aIdx].GetScreen();
return NULL;
}
EDA_ITEM* PICKED_ITEMS_LIST::GetPickedItemLink( unsigned int aIdx ) const
{
if( aIdx < m_ItemsList.size() )

View File

@ -311,17 +311,6 @@ MAGNETIC_SETTINGS* DISPLAY_FOOTPRINTS_FRAME::GetMagneticItemsSettings()
}
/**
* Virtual function needed by the PCB_SCREEN class derived from BASE_SCREEN
* this is a virtual pure function in BASE_SCREEN
* do nothing in Cvpcb
* could be removed later
*/
void PCB_SCREEN::ClearUndoORRedoList( UNDO_REDO_CONTAINER&, int )
{
}
COLOR4D DISPLAY_FOOTPRINTS_FRAME::GetGridColor()
{
return COLOR4D( DARKGRAY );

View File

@ -58,18 +58,34 @@ void SCH_EDIT_FRAME::mapExistingAnnotation( std::map<wxString, wxString>& aMap )
}
void SCH_EDIT_FRAME::DeleteAnnotation( bool aCurrentSheetOnly )
void SCH_EDIT_FRAME::DeleteAnnotation( bool aCurrentSheetOnly, bool* aAppendUndo )
{
auto clearAnnotation =
[&]( SCH_SCREEN* aScreen, SCH_SHEET_PATH* aSheet )
{
for( SCH_ITEM* item : aScreen->Items().OfType( SCH_COMPONENT_T ) )
{
SCH_COMPONENT* component = static_cast<SCH_COMPONENT*>( item );
SaveCopyInUndoList( aScreen, component, UR_CHANGED, *aAppendUndo );
*aAppendUndo = true;
component->ClearAnnotation( aSheet );
// Clear the modified component flag set by component->ClearAnnotation
// because we do not use it here and we should not leave this flag set,
// when an editing is finished:
component->ClearFlags();
}
};
if( aCurrentSheetOnly )
{
SCH_SCREEN* screen = GetScreen();
wxCHECK_RET( screen != NULL, wxT( "Attempt to clear annotation of a NULL screen." ) );
screen->ClearAnnotation( &GetCurrentSheet() );
clearAnnotation( GetScreen(), &GetCurrentSheet() );
}
else
{
SCH_SCREENS ScreenList( Schematic().Root() );
ScreenList.ClearAnnotation();
for( const SCH_SHEET_PATH& sheet : Schematic().GetSheets() )
clearAnnotation( sheet.LastScreen(), nullptr );
}
// Update the references for the sheet that is currently being displayed.
@ -91,11 +107,9 @@ void SCH_EDIT_FRAME::AnnotateComponents( bool aAnnotateSchematic,
REPORTER& aReporter )
{
SCH_REFERENCE_LIST references;
SCH_SCREENS screens( Schematic().Root() );
// Build the sheet list.
SCH_SHEET_LIST sheets = Schematic().GetSheets();
SCH_SCREENS screens( Schematic().Root() );
SCH_SHEET_LIST sheets = Schematic().GetSheets();
bool appendUndo = false;
// Map of locked components
SCH_MULTI_UNIT_REFERENCE_MAP lockedComponents;
@ -132,7 +146,7 @@ void SCH_EDIT_FRAME::AnnotateComponents( bool aAnnotateSchematic,
// If it is an annotation for all the components, reset previous annotation.
if( aResetAnnotation )
DeleteAnnotation( !aAnnotateSchematic );
DeleteAnnotation( !aAnnotateSchematic, &appendUndo );
// Set sheet number and number of sheets.
SetSheetNumberAndCount();
@ -175,21 +189,25 @@ void SCH_EDIT_FRAME::AnnotateComponents( bool aAnnotateSchematic,
// Recalculate and update reference numbers in schematic
references.Annotate( useSheetNum, idStep, aStartNumber, lockedComponents );
references.UpdateAnnotation();
for( size_t i = 0; i < references.GetCount(); i++ )
{
SCH_COMPONENT* comp = references[ i ].GetComp();
SCH_SHEET_PATH* curr_sheetpath = &references[ i ].GetSheetPath();
KIID_PATH curr_full_uuid = curr_sheetpath->Path();
curr_full_uuid.push_back( comp->m_Uuid );
SCH_REFERENCE& ref = references[i];
SCH_COMPONENT* comp = ref.GetComp();
SCH_SHEET_PATH* sheet = &ref.GetSheetPath();
wxString prevRef = previousAnnotation[ curr_full_uuid.AsString() ];
SaveCopyInUndoList( sheet->LastScreen(), comp, UR_CHANGED, appendUndo );
appendUndo = true;
ref.Annotate();
wxString newRef = comp->GetRef( curr_sheetpath );
KIID_PATH full_uuid = sheet->Path();
full_uuid.push_back( comp->m_Uuid );
wxString prevRef = previousAnnotation[ full_uuid.AsString() ];
wxString newRef = comp->GetRef( sheet );
if( comp->GetUnitCount() > 1 )
newRef << LIB_PART::SubReference( comp->GetUnitSelection( curr_sheetpath ) );
newRef << LIB_PART::SubReference( comp->GetUnitSelection( sheet ) );
wxString msg;
@ -202,11 +220,13 @@ void SCH_EDIT_FRAME::AnnotateComponents( bool aAnnotateSchematic,
msg.Printf( _( "Updated %s (unit %s) from %s to %s" ),
comp->GetField( VALUE )->GetShownText(),
LIB_PART::SubReference( comp->GetUnit(), false ),
prevRef, newRef );
prevRef,
newRef );
else
msg.Printf( _( "Updated %s from %s to %s" ),
comp->GetField( VALUE )->GetShownText(),
prevRef, newRef );
prevRef,
newRef );
}
else
{

View File

@ -84,12 +84,13 @@ bool SCH_EDIT_FRAME::TestDanglingEnds()
bool SCH_EDIT_FRAME::TrimWire( const wxPoint& aStart, const wxPoint& aEnd )
{
bool retval = false;
SCH_SCREEN* screen = GetScreen();
bool retval = false;
if( aStart == aEnd )
return retval;
for( auto item : GetScreen()->Items().OfType( SCH_LINE_T ) )
for( EDA_ITEM* item : screen->Items().OfType( SCH_LINE_T ) )
{
SCH_LINE* line = static_cast<SCH_LINE*>( item );
@ -117,17 +118,19 @@ bool SCH_EDIT_FRAME::TrimWire( const wxPoint& aStart, const wxPoint& aEnd )
// Ensure that *line points to the segment containing aEnd
SCH_LINE* return_line = line;
BreakSegment( line, aStart, &return_line );
if( IsPointOnSegment( return_line->GetStartPoint(), return_line->GetEndPoint(), aEnd ) )
line = return_line;
// Step 2: break the remaining segment. return_line remains line if not broken.
// Ensure that *line _also_ contains aStart. This is our overlapping segment
BreakSegment( line, aEnd, &return_line );
if( IsPointOnSegment( return_line->GetStartPoint(), return_line->GetEndPoint(), aStart ) )
line = return_line;
SaveCopyInUndoList( line, UR_DELETED, true );
RemoveFromScreen( line );
SaveCopyInUndoList( screen, line, UR_DELETED, true );
RemoveFromScreen( line, screen );
retval = true;
}
@ -148,11 +151,12 @@ bool SCH_EDIT_FRAME::SchematicCleanUp( SCH_SCREEN* aScreen )
if( aScreen == nullptr )
aScreen = GetScreen();
auto remove_item = [&itemList, &deletedItems]( SCH_ITEM* aItem ) -> void {
aItem->SetFlags( STRUCT_DELETED );
itemList.PushItem( ITEM_PICKER( aItem, UR_DELETED ) );
deletedItems.push_back( aItem );
};
auto remove_item = [&itemList, &deletedItems, &aScreen]( SCH_ITEM* aItem ) -> void
{
aItem->SetFlags( STRUCT_DELETED );
itemList.PushItem( ITEM_PICKER( aScreen, aItem, UR_DELETED ) );
deletedItems.push_back( aItem );
};
BreakSegmentsOnJunctions( aScreen );
@ -245,7 +249,7 @@ bool SCH_EDIT_FRAME::SchematicCleanUp( SCH_SCREEN* aScreen )
{
remove_item( firstLine );
remove_item( secondLine );
itemList.PushItem( ITEM_PICKER( mergedLine, UR_NEW ) );
itemList.PushItem( ITEM_PICKER( aScreen, mergedLine, UR_NEW ) );
AddToScreen( mergedLine, aScreen );
@ -288,8 +292,8 @@ bool SCH_EDIT_FRAME::BreakSegment( SCH_LINE* aSegment, const wxPoint& aPoint,
newSegment->SetStartPoint( aPoint );
AddToScreen( newSegment, aScreen );
SaveCopyInUndoList( newSegment, UR_NEW, true );
SaveCopyInUndoList( aSegment, UR_CHANGED, true );
SaveCopyInUndoList( aScreen, newSegment, UR_NEW, true );
SaveCopyInUndoList( aScreen, aSegment, UR_CHANGED, true );
RefreshItem( aSegment );
aSegment->SetEndPoint( aPoint );
@ -362,11 +366,11 @@ void SCH_EDIT_FRAME::DeleteJunction( SCH_ITEM* aJunction, bool aAppend )
auto remove_item = [ & ]( SCH_ITEM* aItem ) -> void
{
aItem->SetFlags( STRUCT_DELETED );
undoList.PushItem( ITEM_PICKER( aItem, UR_DELETED ) );
undoList.PushItem( ITEM_PICKER( screen, aItem, UR_DELETED ) );
};
remove_item( aJunction );
RemoveFromScreen( aJunction );
RemoveFromScreen( aJunction, screen );
/// Note that std::list or similar is required here as we may insert values in the
/// loop below. This will invalidate iterators in a std::vector or std::deque
@ -401,8 +405,8 @@ void SCH_EDIT_FRAME::DeleteJunction( SCH_ITEM* aJunction, bool aAppend )
{
remove_item( firstLine );
remove_item( secondLine );
undoList.PushItem( ITEM_PICKER( line, UR_NEW ) );
AddToScreen( line );
undoList.PushItem( ITEM_PICKER( screen, line, UR_NEW ) );
AddToScreen( line, screen );
if( line->IsSelected() )
selectionTool->AddItemToSel( line, true /*quiet mode*/ );
@ -421,18 +425,19 @@ void SCH_EDIT_FRAME::DeleteJunction( SCH_ITEM* aJunction, bool aAppend )
if( line->IsSelected() )
selectionTool->RemoveItemFromSel( line, true /*quiet mode*/ );
RemoveFromScreen( line );
RemoveFromScreen( line, screen );
}
}
}
SCH_JUNCTION* SCH_EDIT_FRAME::AddJunction( const wxPoint& aPos, bool aUndoAppend, bool aFinal )
SCH_JUNCTION* SCH_EDIT_FRAME::AddJunction( SCH_SCREEN* aScreen, const wxPoint& aPos,
bool aUndoAppend, bool aFinal )
{
SCH_JUNCTION* junction = new SCH_JUNCTION( aPos );
AddToScreen( junction );
SaveCopyInUndoList( junction, UR_NEW, aUndoAppend );
AddToScreen( junction, aScreen );
SaveCopyInUndoList( aScreen, junction, UR_NEW, aUndoAppend );
BreakSegments( aPos );
if( aFinal )

View File

@ -1,8 +1,3 @@
/**
* @file dialog_annotate.cpp
* @brief Annotation dialog functions.
*/
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
@ -30,11 +25,8 @@
#include <fctsys.h>
#include <sch_edit_frame.h>
#include <sch_draw_panel.h>
#include <bitmaps.h>
#include <confirm.h>
#include <invoke_sch_dialog.h>
#include <dialog_annotate_base.h>
#include <eeschema_settings.h>
#include <kiface_i.h>
@ -59,7 +51,7 @@ private:
/// Initialises member variables
void InitValues();
void OnClearAnnotationCmpClick( wxCommandEvent& event ) override;
void OnClearAnnotationClick( wxCommandEvent& event ) override;
void OnCloseClick( wxCommandEvent& event ) override;
void OnClose( wxCloseEvent& event ) override;
void OnApplyClick( wxCommandEvent& event ) override;
@ -132,7 +124,7 @@ DIALOG_ANNOTATE::~DIALOG_ANNOTATE()
void DIALOG_ANNOTATE::InitValues()
{
auto cfg = static_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
EESCHEMA_SETTINGS* cfg = static_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
int option;
// These are always reset to attempt to keep the user out of trouble...
@ -144,12 +136,8 @@ void DIALOG_ANNOTATE::InitValues()
switch( option )
{
default:
case 0:
m_rbSortBy_X_Position->SetValue( true );
break;
case 1:
m_rbSortBy_Y_Position->SetValue( true );
break;
case 0: m_rbSortBy_X_Position->SetValue( true ); break;
case 1: m_rbSortBy_Y_Position->SetValue( true ); break;
}
option = cfg->m_AnnotatePanel.method;
@ -157,15 +145,9 @@ void DIALOG_ANNOTATE::InitValues()
switch( option )
{
default:
case 0:
m_rbFirstFree->SetValue( true );
break;
case 1:
m_rbSheetX100->SetValue( true );
break;
case 2:
m_rbSheetX1000->SetValue( true );
break;
case 0: m_rbFirstFree->SetValue( true ); break;
case 1: m_rbSheetX100->SetValue( true ); break;
case 2: m_rbSheetX1000->SetValue( true ); break;
}
m_textNumberAfter->SetValue( wxT( "0" ) );
@ -194,26 +176,6 @@ void DIALOG_ANNOTATE::OnClose( wxCloseEvent& event )
void DIALOG_ANNOTATE::OnApplyClick( wxCommandEvent& event )
{
wxString message;
// Ask for confirmation of destructive actions.
if( GetResetItems() )
{
if( GetLevel() )
message += _( "Clear and annotate all of the symbols on the entire schematic?" );
else
message += _( "Clear and annotate all of the symbols on the current sheet?" );
message += _( "\n\nThis operation will change the current annotation and cannot be undone." );
KIDIALOG dlg( this, message, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
dlg.SetOKLabel( _( "Clear and Annotate" ) );
dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
if( dlg.ShowModal() == wxID_CANCEL )
return;
}
m_MessageWindow->Clear();
REPORTER& reporter = m_MessageWindow->Reporter();
m_MessageWindow->SetLazyUpdate( true ); // Don't update after each message
@ -222,7 +184,7 @@ void DIALOG_ANNOTATE::OnApplyClick( wxCommandEvent& event )
(ANNOTATE_OPTION_T) GetAnnotateAlgo(), GetStartNumber(),
GetResetItems() , true, GetLockUnits(), reporter );
m_MessageWindow->Flush( true ); // Now update to show all messages
m_MessageWindow->Flush( true ); // Now update to show all messages
m_Parent->GetCanvas()->Refresh();
@ -241,25 +203,11 @@ void DIALOG_ANNOTATE::OnApplyClick( wxCommandEvent& event )
}
void DIALOG_ANNOTATE::OnClearAnnotationCmpClick( wxCommandEvent& event )
void DIALOG_ANNOTATE::OnClearAnnotationClick( wxCommandEvent& event )
{
wxString message;
bool appendUndo = false;
if( GetLevel() )
message = _( "Clear the existing annotation for the entire schematic?" );
else
message = _( "Clear the existing annotation for the current sheet?" );
message += _( "\n\nThis operation will clear the existing annotation and cannot be undone." );
KIDIALOG dlg( this, message, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
dlg.SetOKLabel( _( "Clear Annotation" ) );
dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
if( dlg.ShowModal() == wxID_CANCEL )
return;
m_Parent->DeleteAnnotation( !GetLevel() );
m_Parent->DeleteAnnotation( !GetLevel(), &appendUndo );
m_btnClear->Enable( false );
}

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Jul 10 2019)
// C++ code generated with wxFormBuilder (version Oct 26 2018)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -35,10 +35,10 @@ DIALOG_ANNOTATE_BASE::DIALOG_ANNOTATE_BASE( wxWindow* parent, wxWindowID id, con
fgSizer1->SetFlexibleDirection( wxBOTH );
fgSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
wxString m_rbScopeChoices[] = { _("Use the entire schematic"), _("Use the current page only") };
wxString m_rbScopeChoices[] = { _("Entire schematic"), _("Current sheet only") };
int m_rbScopeNChoices = sizeof( m_rbScopeChoices ) / sizeof( wxString );
m_rbScope = new wxRadioBox( this, wxID_ANY, _("Scope:"), wxDefaultPosition, wxDefaultSize, m_rbScopeNChoices, m_rbScopeChoices, 1, wxRA_SPECIFY_COLS );
m_rbScope->SetSelection( 0 );
m_rbScope->SetSelection( 1 );
fgSizer1->Add( m_rbScope, 0, wxALL|wxEXPAND, 5 );
wxStaticBoxSizer* sbSizer1;
@ -148,7 +148,7 @@ DIALOG_ANNOTATE_BASE::DIALOG_ANNOTATE_BASE( wxWindow* parent, wxWindowID id, con
// Connect Events
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_ANNOTATE_BASE::OnClose ) );
m_btnClear->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_ANNOTATE_BASE::OnClearAnnotationCmpClick ), NULL, this );
m_btnClear->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_ANNOTATE_BASE::OnClearAnnotationClick ), NULL, this );
m_sdbSizer1Cancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_ANNOTATE_BASE::OnCloseClick ), NULL, this );
m_sdbSizer1OK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_ANNOTATE_BASE::OnApplyClick ), NULL, this );
}
@ -157,7 +157,7 @@ DIALOG_ANNOTATE_BASE::~DIALOG_ANNOTATE_BASE()
{
// Disconnect Events
this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_ANNOTATE_BASE::OnClose ) );
m_btnClear->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_ANNOTATE_BASE::OnClearAnnotationCmpClick ), NULL, this );
m_btnClear->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_ANNOTATE_BASE::OnClearAnnotationClick ), NULL, this );
m_sdbSizer1Cancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_ANNOTATE_BASE::OnCloseClick ), NULL, this );
m_sdbSizer1OK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_ANNOTATE_BASE::OnApplyClick ), NULL, this );

View File

@ -14,7 +14,6 @@
<property name="file">dialog_annotate_base</property>
<property name="first_id">1000</property>
<property name="help_provider">none</property>
<property name="image_path_wrapper_function_name"></property>
<property name="indent_with_spaces"></property>
<property name="internationalize">1</property>
<property name="name">dialog_annotate_base</property>
@ -26,7 +25,6 @@
<property name="skip_php_events">1</property>
<property name="skip_python_events">1</property>
<property name="ui_table">UI</property>
<property name="use_array_enum">0</property>
<property name="use_enum">0</property>
<property name="use_microsoft_bom">0</property>
<object class="Dialog" expanded="1">
@ -165,7 +163,7 @@
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="choices">&quot;Use the entire schematic&quot; &quot;Use the current page only&quot;</property>
<property name="choices">&quot;Entire schematic&quot; &quot;Current sheet only&quot;</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
@ -197,7 +195,7 @@
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="selection">0</property>
<property name="selection">1</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxRA_SPECIFY_COLS</property>
@ -1018,7 +1016,7 @@
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnButtonClick">OnClearAnnotationCmpClick</event>
<event name="OnButtonClick">OnClearAnnotationClick</event>
</object>
</object>
<object class="sizeritem" expanded="1">

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Jul 10 2019)
// C++ code generated with wxFormBuilder (version Oct 26 2018)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -69,7 +69,7 @@ class DIALOG_ANNOTATE_BASE : public DIALOG_SHIM
// Virtual event handlers, overide them in your derived class
virtual void OnClose( wxCloseEvent& event ) { event.Skip(); }
virtual void OnClearAnnotationCmpClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnClearAnnotationClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnCloseClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnApplyClick( wxCommandEvent& event ) { event.Skip(); }

View File

@ -415,7 +415,7 @@ bool DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::TransferDataFromWindow()
// save old cmp in undo list if not already in edit, or moving ...
if( m_cmp->GetEditFlags() == 0 )
GetParent()->SaveCopyInUndoList( m_cmp, UR_CHANGED );
GetParent()->SaveCopyInUndoList( currentScreen, m_cmp, UR_CHANGED, false );
// Save current flags which could be modified by next change settings
STATUS_FLAGS flags = m_cmp->GetFlags();
@ -525,19 +525,23 @@ bool DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::TransferDataFromWindow()
// should be kept in sync in multi-unit parts.
if( m_cmp->GetUnitCount() > 1 )
{
std::vector<SCH_COMPONENT*> otherUnits;
CollectOtherUnits( GetParent()->GetCurrentSheet(), m_cmp, &otherUnits );
for( SCH_COMPONENT* otherUnit : otherUnits )
for( SCH_SHEET_PATH& sheet : GetParent()->Schematic().GetSheets() )
{
GetParent()->SaveCopyInUndoList( otherUnit, UR_CHANGED, true /* append */);
otherUnit->GetField( VALUE )->SetText( m_fields->at( VALUE ).GetText() );
otherUnit->GetField( FOOTPRINT )->SetText( m_fields->at( FOOTPRINT ).GetText() );
otherUnit->GetField( DATASHEET )->SetText( m_fields->at( DATASHEET ).GetText() );
otherUnit->SetIncludeInBom( !m_cbExcludeFromBom->IsChecked() );
otherUnit->SetIncludeOnBoard( !m_cbExcludeFromBoard->IsChecked() );
GetParent()->RefreshItem( otherUnit );
SCH_SCREEN* screen = sheet.LastScreen();
std::vector<SCH_COMPONENT*> otherUnits;
CollectOtherUnits( sheet, m_cmp, &otherUnits );
for( SCH_COMPONENT* otherUnit : otherUnits )
{
GetParent()->SaveCopyInUndoList( screen, otherUnit, UR_CHANGED, true /* append */);
otherUnit->GetField( VALUE )->SetText( m_fields->at( VALUE ).GetText() );
otherUnit->GetField( FOOTPRINT )->SetText( m_fields->at( FOOTPRINT ).GetText() );
otherUnit->GetField( DATASHEET )->SetText( m_fields->at( DATASHEET ).GetText() );
otherUnit->SetIncludeInBom( !m_cbExcludeFromBom->IsChecked() );
otherUnit->SetIncludeOnBoard( !m_cbExcludeFromBoard->IsChecked() );
GetParent()->RefreshItem( otherUnit );
}
}
}
@ -725,9 +729,7 @@ void DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::UpdateFieldsFromLibrary( wxCommandEvent
copy.SetLibSymbol( libSymbol->Flatten().release() );
// Update the requested fields in the component copy
std::list<SCH_COMPONENT*> components;
components.push_back( &copy );
InvokeDialogUpdateFields( GetParent(), components, false );
InvokeDialogUpdateFields( GetParent(), &copy, false );
wxGridTableMessage clear( m_fields, wxGRIDTABLE_NOTIFY_ROWS_DELETED, 0, m_fields->size() );
m_grid->ProcessTableMessage( clear );

View File

@ -395,7 +395,7 @@ bool DIALOG_LABEL_EDITOR::TransferDataFromWindow()
/* save old text in undo list if not already in edit */
if( m_CurrentText->GetEditFlags() == 0 )
m_Parent->SaveCopyInUndoList( m_CurrentText, UR_CHANGED );
m_Parent->SaveCopyInUndoList( m_Parent->GetScreen(), m_CurrentText, UR_CHANGED, false );
m_Parent->GetCanvas()->Refresh();

View File

@ -211,10 +211,10 @@ bool DIALOG_EDIT_LINE_STYLE::TransferDataFromWindow()
PICKED_ITEMS_LIST pickedItems;
STROKE_PARAMS stroke;
for( auto& strokeItem : m_strokeItems )
pickedItems.PushItem( ITEM_PICKER( strokeItem, UR_CHANGED ) );
for( SCH_ITEM* strokeItem : m_strokeItems )
pickedItems.PushItem( ITEM_PICKER( m_frame->GetScreen(), strokeItem, UR_CHANGED ) );
m_frame->SaveCopyInUndoList( pickedItems, UR_CHANGED );
m_frame->SaveCopyInUndoList( pickedItems, UR_CHANGED, false );
for( auto& strokeItem : m_strokeItems )
{

View File

@ -405,22 +405,26 @@ void DIALOG_SCH_EDIT_ONE_FIELD::UpdateField( SCH_FIELD* aField, SCH_SHEET_PATH*
aField->SetText( m_text );
updateText( aField );
// The value, footprint and datasheet fields should be kept in sync in multi-unit
// parts.
// The value, footprint and datasheet fields should be kept in sync in multi-unit parts.
// Of course the component must be annotated to collect other units.
if( editFrame && parent && parent->Type() == SCH_COMPONENT_T
&& ( fieldType == VALUE || fieldType == FOOTPRINT || fieldType == DATASHEET ) )
{
SCH_COMPONENT* thisUnit = static_cast<SCH_COMPONENT*>( parent );
std::vector<SCH_COMPONENT*> otherUnits;
CollectOtherUnits( editFrame->GetCurrentSheet(), thisUnit, &otherUnits );
for( SCH_COMPONENT* otherUnit : otherUnits )
for( SCH_SHEET_PATH& sheet : editFrame->Schematic().GetSheets() )
{
editFrame->SaveCopyInUndoList( otherUnit, UR_CHANGED, true /* append */);
otherUnit->GetField( fieldType )->SetText( m_text );
editFrame->RefreshItem( otherUnit );
SCH_SCREEN* screen = sheet.LastScreen();
std::vector<SCH_COMPONENT*> otherUnits;
CollectOtherUnits( sheet, thisUnit, &otherUnits );
for( SCH_COMPONENT* otherUnit : otherUnits )
{
editFrame->SaveCopyInUndoList( screen, otherUnit, UR_CHANGED, true /* append */);
otherUnit->GetField( fieldType )->SetText( m_text );
editFrame->RefreshItem( otherUnit );
}
}
}

View File

@ -97,7 +97,10 @@ bool DIALOG_EDIT_SHEET_PIN::TransferDataToWindow()
bool DIALOG_EDIT_SHEET_PIN::TransferDataFromWindow()
{
if( !m_sheetPin->IsNew() )
m_frame->SaveCopyInUndoList( (SCH_ITEM*) m_sheetPin->GetParent(), UR_CHANGED );
{
SCH_SHEET* parentSheet = m_sheetPin->GetParent();
m_frame->SaveCopyInUndoList( m_frame->GetScreen(), parentSheet, UR_CHANGED, false );
}
m_sheetPin->SetText( EscapeString( m_comboName->GetValue(), CTX_NETNAME ) );
// Currently, eeschema uses only the text width as text size,

View File

@ -600,9 +600,9 @@ public:
for( unsigned i = 0; i < m_componentRefs.GetCount(); ++i )
{
SCH_COMPONENT& comp = *m_componentRefs[i].GetComp();
SCH_SCREEN* screen = m_componentRefs[i].GetSheetPath().LastScreen();
m_frame->SetCurrentSheet( m_componentRefs[i].GetSheetPath() );
m_frame->SaveCopyInUndoList( &comp, UR_CHANGED, true );
m_frame->SaveCopyInUndoList( screen, &comp, UR_CHANGED, true );
const std::map<wxString, wxString>& fieldStore = m_dataStore[comp.m_Uuid];

View File

@ -218,7 +218,7 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::processItem( const SCH_SHEET_PATH& aS
auto sch_text = dynamic_cast<SCH_TEXT*>( aItem );
auto lineItem = dynamic_cast<SCH_LINE*>( aItem );
m_parent->SaveCopyInUndoList( aItem, UR_CHANGED, m_hasChange );
m_parent->SaveCopyInUndoList( aSheetPath.LastScreen(), aItem, UR_CHANGED, m_hasChange );
if( eda_text )
{

View File

@ -171,10 +171,10 @@ bool DIALOG_JUNCTION_PROPS::TransferDataFromWindow()
{
PICKED_ITEMS_LIST pickedItems;
for( auto& junction : m_junctions )
pickedItems.PushItem( ITEM_PICKER( junction, UR_CHANGED ) );
for( SCH_JUNCTION* junction : m_junctions )
pickedItems.PushItem( ITEM_PICKER( m_frame->GetScreen(), junction, UR_CHANGED ) );
m_frame->SaveCopyInUndoList( pickedItems, UR_CHANGED );
m_frame->SaveCopyInUndoList( pickedItems, UR_CHANGED, false );
for( auto& junction : m_junctions )
{

View File

@ -481,7 +481,7 @@ bool DIALOG_SCH_SHEET_PROPS::onSheetFilenameChanged( const wxString& aNewFilenam
}
if( isUndoable )
m_frame->SaveCopyInUndoList( m_sheet, UR_CHANGED );
m_frame->SaveCopyInUndoList( m_frame->GetScreen(), m_sheet, UR_CHANGED, false );
if( renameFile )
{

View File

@ -99,7 +99,7 @@ void DIALOG_SYMBOL_REMAP::OnRemapSymbols( wxCommandEvent& aEvent )
if( viewer )
viewer->ReCreateListLib();
parent->GetScreen()->ClearUndoORRedoList( parent->GetScreen()->m_UndoList, 1 );
parent->ClearUndoORRedoList( parent->m_UndoList, 1 );
parent->SyncView();
parent->GetCanvas()->Refresh();
parent->OnModify();

View File

@ -28,23 +28,41 @@
#include <sch_edit_frame.h>
#include <sch_component.h>
#include <schematic.h>
#include <class_libentry.h>
#include <algorithm>
int InvokeDialogUpdateFields( SCH_EDIT_FRAME* aCaller,
const list<SCH_COMPONENT*> aComponents, bool aCreateUndoEntry )
int InvokeDialogUpdateFields( SCH_EDIT_FRAME* aCaller, SCH_COMPONENT* aSpecificComponent,
bool aCreateUndoEntry )
{
DIALOG_UPDATE_FIELDS dlg( aCaller, aComponents, aCreateUndoEntry );
DIALOG_UPDATE_FIELDS dlg( aCaller, aSpecificComponent, aCreateUndoEntry );
return dlg.ShowQuasiModal();
}
DIALOG_UPDATE_FIELDS::DIALOG_UPDATE_FIELDS( SCH_EDIT_FRAME* aParent,
const list<SCH_COMPONENT*>& aComponents, bool aCreateUndoEntry )
: DIALOG_UPDATE_FIELDS_BASE( aParent ), m_frame( aParent ),
m_components( aComponents ), m_createUndo( aCreateUndoEntry )
SCH_COMPONENT* aSpecificComponent,
bool aCreateUndoEntry ) :
DIALOG_UPDATE_FIELDS_BASE( aParent ),
m_frame( aParent ),
m_createUndo( aCreateUndoEntry )
{
if( aSpecificComponent )
{
m_components.emplace_back( aParent->GetScreen(), aSpecificComponent );
}
else
{
for( SCH_SHEET_PATH& path : aParent->Schematic().GetSheets() )
{
SCH_SCREEN* screen = path.LastScreen();
for( SCH_ITEM* item : screen->Items().OfType( SCH_COMPONENT_T ) )
m_components.emplace_back( screen, static_cast<SCH_COMPONENT*>( item ) );
}
}
m_sdbSizerOK->SetDefault();
}
@ -57,7 +75,6 @@ bool DIALOG_UPDATE_FIELDS::TransferDataFromWindow()
if( m_components.empty() )
return true; // nothing to process
// Create the set of fields to be updated
m_updateFields.clear();
@ -73,16 +90,16 @@ bool DIALOG_UPDATE_FIELDS::TransferDataFromWindow()
{
PICKED_ITEMS_LIST itemsList;
for( auto component : m_components )
itemsList.PushItem( ITEM_PICKER( component, UR_CHANGED ) );
for( std::pair<SCH_SCREEN*, SCH_COMPONENT*>& component : m_components )
itemsList.PushItem( ITEM_PICKER( component.first, component.second, UR_CHANGED ) );
m_frame->SaveCopyInUndoList( itemsList, UR_CHANGED );
m_frame->SaveCopyInUndoList( itemsList, UR_CHANGED, true );
}
// Do it!
for( auto component : m_components )
updateFields( component );
for( std::pair<SCH_SCREEN*, SCH_COMPONENT*>& component : m_components )
updateFields( component.second );
m_frame->SyncView();
m_frame->GetCanvas()->Refresh();
@ -99,9 +116,9 @@ bool DIALOG_UPDATE_FIELDS::TransferDataToWindow()
// Collect all user field names from library parts of components that are going to be updated
{
for( auto component : m_components )
for( std::pair<SCH_SCREEN*, SCH_COMPONENT*>& component : m_components )
{
const std::unique_ptr< LIB_PART >& part = component->GetPartRef();
const std::unique_ptr< LIB_PART >& part = component.second->GetPartRef();
if( !part )
continue;
@ -123,7 +140,7 @@ bool DIALOG_UPDATE_FIELDS::TransferDataToWindow()
for( int i = 0; i < MANDATORY_FIELDS; ++i )
{
m_fieldsBox->Append( m_components.front()->GetField( i )->GetName() );
m_fieldsBox->Append( m_components.front().second->GetField( i )->GetName() );
if( i != REFERENCE && i != VALUE )
m_fieldsBox->Check( i, true );

View File

@ -34,17 +34,14 @@ class SCH_COMPONENT;
class SCH_SCREEN;
class SCH_EDIT_FRAME;
using std::set;
using std::list;
/**
* Dialog to update component fields (i.e. restore them from the original library symbols).
*/
class DIALOG_UPDATE_FIELDS : public DIALOG_UPDATE_FIELDS_BASE
{
public:
DIALOG_UPDATE_FIELDS( SCH_EDIT_FRAME* aParent, const list<SCH_COMPONENT*>& aComponents,
bool aCreateUndoEntry = true );
DIALOG_UPDATE_FIELDS( SCH_EDIT_FRAME* aParent, SCH_COMPONENT* aComponent,
bool aCreateUndoEntry );
private:
bool TransferDataFromWindow() override;
@ -66,16 +63,14 @@ private:
checkAll( false );
}
///> Parent frame
SCH_EDIT_FRAME* m_frame;
///> Set of field names that should have values updated
set<wxString> m_updateFields;
std::set<wxString> m_updateFields;
///> Components to update
list<SCH_COMPONENT*> m_components;
std::vector< std::pair<SCH_SCREEN*, SCH_COMPONENT*>> m_components;
///> Flag indicating whether an undo buffer entry should be created
bool m_createUndo;
};

View File

@ -492,7 +492,7 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
GetScreen()->TestDanglingEnds(); // Only perform the dangling end test on root sheet.
RecalculateConnections( GLOBAL_CLEANUP );
GetScreen()->ClearUndoORRedoList( GetScreen()->m_UndoList, 1 );
ClearUndoRedoList();
GetScreen()->m_Initialized = true;
}
@ -872,10 +872,11 @@ bool SCH_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType )
}
}
}
// Only perform the dangling end test on root sheet.
GetScreen()->TestDanglingEnds();
GetScreen()->ClearUndoORRedoList( GetScreen()->m_UndoList, 1 );
ClearUndoRedoList();
m_toolManager->RunAction( ACTIONS::zoomFitScreen, true );
SetSheetNumberAndCount();

View File

@ -211,7 +211,7 @@ void SCH_EDIT_FRAME::SelectUnit( SCH_COMPONENT* aComponent, int aUnit )
STATUS_FLAGS savedFlags = aComponent->GetFlags();
if( !aComponent->GetEditFlags() ) // No command in progress: save in undo list
SaveCopyInUndoList( aComponent, UR_CHANGED );
SaveCopyInUndoList( GetScreen(), aComponent, UR_CHANGED, false );
/* Update the unit number. */
aComponent->SetUnitSelection( &GetCurrentSheet(), aUnit );

Some files were not shown because too many files have changed in this diff Show More