Allow Net Inspector to create, rename and delete nets.

ADDED: create/edit/delete nets in PCBnew Net Inspector
ADDED: update from PCB now allows updating of changed nets

Fixes https://gitlab.com/kicad/code/kicad/issues/1996
This commit is contained in:
Jeff Young 2020-06-08 19:36:25 +01:00
parent 570cc61b3f
commit e325d2e18f
22 changed files with 1182 additions and 513 deletions

View File

@ -36,7 +36,7 @@
#include <wx/textctrl.h> #include <wx/textctrl.h>
#include <wx/textentry.h> #include <wx/textentry.h>
#include <wx/log.h> #include <wx/log.h>
#include <wx/combo.h>
GRID_CELL_TEXT_EDITOR::GRID_CELL_TEXT_EDITOR() : wxGridCellTextEditor() GRID_CELL_TEXT_EDITOR::GRID_CELL_TEXT_EDITOR() : wxGridCellTextEditor()
{ {
@ -316,6 +316,63 @@ bool LIB_ID_VALIDATOR::Validate( wxWindow *aParent )
} }
NETNAME_VALIDATOR::NETNAME_VALIDATOR( wxString *aVal ) :
wxTextValidator(),
m_allowSpaces( false )
{
}
NETNAME_VALIDATOR::NETNAME_VALIDATOR( const NETNAME_VALIDATOR& aValidator ) :
wxTextValidator( aValidator ),
m_allowSpaces( aValidator.m_allowSpaces )
{
}
NETNAME_VALIDATOR::NETNAME_VALIDATOR( bool aAllowSpaces ) :
wxTextValidator(),
m_allowSpaces( aAllowSpaces )
{
}
bool NETNAME_VALIDATOR::Validate( wxWindow *aParent )
{
// If window is disabled, simply return
if ( !m_validatorWindow->IsEnabled() )
return true;
wxTextEntry * const text = GetTextEntry();
if ( !text )
return false;
const wxString& errormsg = IsValid( text->GetValue() );
if( !errormsg.empty() )
{
m_validatorWindow->SetFocus();
wxMessageBox( errormsg, _( "Invalid signal name" ), wxOK | wxICON_EXCLAMATION, aParent );
return false;
}
return true;
}
wxString NETNAME_VALIDATOR::IsValid( const wxString& str ) const
{
if( str.Contains( '\r' ) || str.Contains( '\n' ) )
return _( "Signal names cannot contain CR or LF characters" );
if( !m_allowSpaces && ( str.Contains( ' ' ) || str.Contains( '\t' ) ) )
return _( "Signal names cannot contain spaces" );
return wxString();
}
void KIUI::ValidatorTransferToWindowWithoutEvents( wxValidator& aValidator ) void KIUI::ValidatorTransferToWindowWithoutEvents( wxValidator& aValidator )
{ {
wxWindow* ctrl = aValidator.GetWindow(); wxWindow* ctrl = aValidator.GetWindow();

View File

@ -1,12 +1,8 @@
/**
* @file eeschema/dialogs/dialog_update_from_pcb.cpp
*/
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2019 Alexander Shuklin <Jasuramme@gmail.com> * Copyright (C) 2019 Alexander Shuklin <Jasuramme@gmail.com>
* Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -27,20 +23,14 @@
*/ */
#include <backannotate.h> #include <backannotate.h>
#include <class_draw_panel_gal.h>
#include <common.h>
#include <confirm.h>
#include <dialog_update_from_pcb.h> #include <dialog_update_from_pcb.h>
#include <functional>
#include <sch_edit_frame.h> #include <sch_edit_frame.h>
#include <sch_editor_control.h> #include <sch_editor_control.h>
#include <tool/tool_manager.h>
#include <view/view.h>
#include <wx_html_report_panel.h> #include <wx_html_report_panel.h>
// Saved dialog settings // Saved dialog settings
DIALOG_UPDATE_FROM_PCB::DIALOG_UPDATE_FROM_PCB_SAVED_STATE DIALOG_UPDATE_FROM_PCB::DIALOG_UPDATE_FROM_PCB_SAVED_STATE
DIALOG_UPDATE_FROM_PCB::s_savedDialogState{ true, false, false, false }; DIALOG_UPDATE_FROM_PCB::s_savedDialogState{ true, true, true, true, false };
DIALOG_UPDATE_FROM_PCB::DIALOG_UPDATE_FROM_PCB( SCH_EDIT_FRAME* aParent ) DIALOG_UPDATE_FROM_PCB::DIALOG_UPDATE_FROM_PCB( SCH_EDIT_FRAME* aParent )
: DIALOG_UPDATE_FROM_PCB_BASE( aParent ), : DIALOG_UPDATE_FROM_PCB_BASE( aParent ),
@ -55,6 +45,7 @@ DIALOG_UPDATE_FROM_PCB::DIALOG_UPDATE_FROM_PCB( SCH_EDIT_FRAME* aParent )
m_cbUpdateReferences->SetValue( s_savedDialogState.UpdateReferences ); m_cbUpdateReferences->SetValue( s_savedDialogState.UpdateReferences );
m_cbUpdateFootprints->SetValue( s_savedDialogState.UpdateFootprints ); m_cbUpdateFootprints->SetValue( s_savedDialogState.UpdateFootprints );
m_cbUpdateValues->SetValue( s_savedDialogState.UpdateValues ); m_cbUpdateValues->SetValue( s_savedDialogState.UpdateValues );
m_cbUpdateNetNames->SetValue( s_savedDialogState.UpdateNetNames );
m_cbIgnoreOtherProjects->SetValue( s_savedDialogState.IgnoreOtherProjectsErrors ); m_cbIgnoreOtherProjects->SetValue( s_savedDialogState.IgnoreOtherProjectsErrors );
// We use a sdbSizer to get platform-dependent ordering of the action buttons, but // We use a sdbSizer to get platform-dependent ordering of the action buttons, but
@ -67,22 +58,23 @@ DIALOG_UPDATE_FROM_PCB::DIALOG_UPDATE_FROM_PCB( SCH_EDIT_FRAME* aParent )
FinishDialogSettings(); FinishDialogSettings();
} }
BACK_ANNOTATE::SETTINGS DIALOG_UPDATE_FROM_PCB::getSettings( bool aDryRun )
{
return BACK_ANNOTATE::SETTINGS{ m_messagePanel->Reporter(), m_cbUpdateFootprints->GetValue(),
m_cbUpdateValues->GetValue(), m_cbUpdateReferences->GetValue(),
m_cbIgnoreOtherProjects->GetValue(), aDryRun };
}
void DIALOG_UPDATE_FROM_PCB::updateData() void DIALOG_UPDATE_FROM_PCB::updateData()
{ {
bool successfulRun = false; bool successfulRun = false;
m_messagePanel->Clear(); m_messagePanel->Clear();
BACK_ANNOTATE backAnno( this->m_frame, getSettings( true ) ); BACK_ANNOTATE backAnno( this->m_frame,
m_messagePanel->Reporter(),
m_cbUpdateFootprints->GetValue(),
m_cbUpdateValues->GetValue(),
m_cbUpdateReferences->GetValue(),
m_cbUpdateNetNames->GetValue(),
m_cbIgnoreOtherProjects->GetValue(),
true );
std::string netlist; std::string netlist;
if( backAnno.FetchNetlistFromPCB( netlist ) ) if( backAnno.FetchNetlistFromPCB( netlist ) )
successfulRun = backAnno.BackAnnotateSymbols( netlist ); successfulRun = backAnno.BackAnnotateSymbols( netlist );
m_sdbSizerOK->Enable( successfulRun ); m_sdbSizerOK->Enable( successfulRun );
m_messagePanel->Flush( false ); m_messagePanel->Flush( false );
} }
@ -103,23 +95,22 @@ void DIALOG_UPDATE_FROM_PCB::OnOptionChanged( wxCommandEvent& event )
s_savedDialogState.UpdateReferences = m_cbUpdateReferences->GetValue(); s_savedDialogState.UpdateReferences = m_cbUpdateReferences->GetValue();
s_savedDialogState.UpdateFootprints = m_cbUpdateFootprints->GetValue(); s_savedDialogState.UpdateFootprints = m_cbUpdateFootprints->GetValue();
s_savedDialogState.UpdateValues = m_cbUpdateValues->GetValue(); s_savedDialogState.UpdateValues = m_cbUpdateValues->GetValue();
s_savedDialogState.UpdateNetNames = m_cbUpdateNetNames->GetValue();
s_savedDialogState.IgnoreOtherProjectsErrors = m_cbIgnoreOtherProjects->GetValue(); s_savedDialogState.IgnoreOtherProjectsErrors = m_cbIgnoreOtherProjects->GetValue();
} }
void DIALOG_UPDATE_FROM_PCB::OnUpdateClick( wxCommandEvent& event ) void DIALOG_UPDATE_FROM_PCB::OnUpdateClick( wxCommandEvent& event )
{ {
KIDIALOG dlg( this,
_( "\n\nThis operation will change the existing annotation and cannot be undone." ),
_( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
dlg.SetOKLabel( _( "Back annotate" ) );
dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
if( dlg.ShowModal() == wxID_CANCEL )
return;
std::string netlist; std::string netlist;
m_messagePanel->Clear(); m_messagePanel->Clear();
BACK_ANNOTATE backAnno( this->m_frame, getSettings( false ) ); BACK_ANNOTATE backAnno( m_frame,
m_messagePanel->Reporter(),
m_cbUpdateFootprints->GetValue(),
m_cbUpdateValues->GetValue(),
m_cbUpdateReferences->GetValue(),
m_cbUpdateNetNames->GetValue(),
m_cbIgnoreOtherProjects->GetValue(),
false );
if( backAnno.FetchNetlistFromPCB( netlist ) && backAnno.BackAnnotateSymbols( netlist ) ) if( backAnno.FetchNetlistFromPCB( netlist ) && backAnno.BackAnnotateSymbols( netlist ) )
{ {

View File

@ -1,12 +1,8 @@
/**
* @file eeschema/dialogs/dialog_update_from_pcb.h
*/
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2019 Alexander Shuklin <Jasuramme@gmail.com> * Copyright (C) 2019 Alexander Shuklin <Jasuramme@gmail.com>
* Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -38,7 +34,6 @@ class SCH_EDITOR_CONTROL;
class DIALOG_UPDATE_FROM_PCB : public DIALOG_UPDATE_FROM_PCB_BASE class DIALOG_UPDATE_FROM_PCB : public DIALOG_UPDATE_FROM_PCB_BASE
{ {
/** /**
* Struct containing the dialog last saved state * Struct containing the dialog last saved state
*/ */
@ -48,6 +43,7 @@ class DIALOG_UPDATE_FROM_PCB : public DIALOG_UPDATE_FROM_PCB_BASE
bool UpdateReferences; bool UpdateReferences;
bool UpdateFootprints; bool UpdateFootprints;
bool UpdateValues; bool UpdateValues;
bool UpdateNetNames;
bool IgnoreOtherProjectsErrors; bool IgnoreOtherProjectsErrors;
}; };
@ -64,13 +60,6 @@ public:
private: private:
void updateData(); void updateData();
/**
* @brief Creates back annotate settings from dialog ui
* @param aDryRun - is it dry run
* @return back annotation settings structure
*/
BACK_ANNOTATE::SETTINGS getSettings( bool aDryRun );
bool TransferDataToWindow() override; bool TransferDataToWindow() override;
void OnOptionChanged( wxCommandEvent& event ) override; void OnOptionChanged( wxCommandEvent& event ) override;
void OnUpdateClick( wxCommandEvent& event ) override; void OnUpdateClick( wxCommandEvent& event ) override;

View File

@ -54,6 +54,12 @@ DIALOG_UPDATE_FROM_PCB_BASE::DIALOG_UPDATE_FROM_PCB_BASE( wxWindow* parent, wxWi
fgSizer1->Add( m_cbUpdateFootprints, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); fgSizer1->Add( m_cbUpdateFootprints, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
fgSizer1->Add( 0, 0, 1, wxEXPAND, 5 );
m_cbUpdateNetNames = new wxCheckBox( sbSizerOptions->GetStaticBox(), wxID_ANY, _("Update net names"), wxDefaultPosition, wxDefaultSize, 0 );
fgSizer1->Add( m_cbUpdateNetNames, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
sbSizerOptions->Add( fgSizer1, 1, wxEXPAND, 5 ); sbSizerOptions->Add( fgSizer1, 1, wxEXPAND, 5 );
@ -91,6 +97,7 @@ DIALOG_UPDATE_FROM_PCB_BASE::DIALOG_UPDATE_FROM_PCB_BASE( wxWindow* parent, wxWi
m_cbIgnoreOtherProjects->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this ); m_cbIgnoreOtherProjects->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbUpdateValues->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this ); m_cbUpdateValues->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbUpdateFootprints->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this ); m_cbUpdateFootprints->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbUpdateNetNames->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this );
m_sdbSizerOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnUpdateClick ), NULL, this ); m_sdbSizerOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnUpdateClick ), NULL, this );
} }
@ -101,6 +108,7 @@ DIALOG_UPDATE_FROM_PCB_BASE::~DIALOG_UPDATE_FROM_PCB_BASE()
m_cbIgnoreOtherProjects->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this ); m_cbIgnoreOtherProjects->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbUpdateValues->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this ); m_cbUpdateValues->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbUpdateFootprints->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this ); m_cbUpdateFootprints->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbUpdateNetNames->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this );
m_sdbSizerOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnUpdateClick ), NULL, this ); m_sdbSizerOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnUpdateClick ), NULL, this );
} }

View File

@ -365,6 +365,81 @@
<event name="OnCheckBox">OnOptionChanged</event> <event name="OnCheckBox">OnOptionChanged</event>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="spacer" expanded="1">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxBOTTOM|wxRIGHT|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxCheckBox" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Update net names</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_cbUpdateNetNames</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnCheckBox">OnOptionChanged</event>
</object>
</object>
</object> </object>
</object> </object>
</object> </object>

View File

@ -39,6 +39,7 @@ class DIALOG_UPDATE_FROM_PCB_BASE : public DIALOG_SHIM
wxCheckBox* m_cbIgnoreOtherProjects; wxCheckBox* m_cbIgnoreOtherProjects;
wxCheckBox* m_cbUpdateValues; wxCheckBox* m_cbUpdateValues;
wxCheckBox* m_cbUpdateFootprints; wxCheckBox* m_cbUpdateFootprints;
wxCheckBox* m_cbUpdateNetNames;
WX_HTML_REPORT_PANEL* m_messagePanel; WX_HTML_REPORT_PANEL* m_messagePanel;
wxStdDialogButtonSizer* m_sdbSizer; wxStdDialogButtonSizer* m_sdbSizer;
wxButton* m_sdbSizerOK; wxButton* m_sdbSizerOK;

View File

@ -142,9 +142,9 @@ SCH_COMPONENT::SCH_COMPONENT( LIB_PART& aPart, LIB_ID aLibId, SCH_SHEET_PATH* sh
} }
SCH_COMPONENT::SCH_COMPONENT( SCH_COMPONENT::SCH_COMPONENT( LIB_PART& aPart, SCH_SHEET_PATH* aSheet, COMPONENT_SELECTION& aSel,
LIB_PART& aPart, SCH_SHEET_PATH* aSheet, COMPONENT_SELECTION& aSel, const wxPoint& pos ) const wxPoint& pos ) :
: SCH_COMPONENT( aPart, aSel.LibId, aSheet, aSel.Unit, aSel.Convert, pos ) SCH_COMPONENT( aPart, aSel.LibId, aSheet, aSel.Unit, aSel.Convert, pos )
{ {
// Set any fields that were modified as part of the component selection // Set any fields that were modified as part of the component selection
for( auto const& i : aSel.Fields ) for( auto const& i : aSel.Fields )
@ -262,9 +262,7 @@ void SCH_COMPONENT::SetLibSymbol( LIB_PART* aLibSymbol )
wxString SCH_COMPONENT::GetDescription() const wxString SCH_COMPONENT::GetDescription() const
{ {
if( m_part ) if( m_part )
{
return m_part->GetDescription(); return m_part->GetDescription();
}
return wxEmptyString; return wxEmptyString;
} }

View File

@ -27,6 +27,7 @@
* @brief Implementation of control validators for schematic dialogs. * @brief Implementation of control validators for schematic dialogs.
*/ */
#include <sch_connection.h>
#include <wx/combo.h> #include <wx/combo.h>
#include <sch_validators.h> #include <sch_validators.h>
#include <project/net_settings.h> #include <project/net_settings.h>
@ -183,73 +184,6 @@ bool SCH_FIELD_VALIDATOR::Validate( wxWindow *aParent )
} }
SCH_NETNAME_VALIDATOR::SCH_NETNAME_VALIDATOR( wxString *aVal )
: wxValidator(),
m_allowSpaces( false )
{
}
SCH_NETNAME_VALIDATOR::SCH_NETNAME_VALIDATOR( const SCH_NETNAME_VALIDATOR& aValidator )
: wxValidator(),
m_allowSpaces( aValidator.m_allowSpaces )
{
}
SCH_NETNAME_VALIDATOR::SCH_NETNAME_VALIDATOR( bool aAllowSpaces )
: wxValidator(),
m_allowSpaces( aAllowSpaces )
{
}
wxTextEntry *SCH_NETNAME_VALIDATOR::GetTextEntry()
{
#if wxUSE_TEXTCTRL
if( wxDynamicCast( m_validatorWindow, wxTextCtrl ) )
return static_cast<wxTextCtrl*>( m_validatorWindow );
#endif
#if wxUSE_COMBOBOX
if( wxDynamicCast( m_validatorWindow, wxComboBox ) )
return static_cast<wxComboBox*>( m_validatorWindow );
#endif
#if wxUSE_COMBOCTRL
if( wxDynamicCast( m_validatorWindow, wxComboCtrl ) )
return static_cast<wxComboCtrl*>( m_validatorWindow );
#endif
wxFAIL_MSG( "SCH_NETNAME_VALIDATOR can only be used with wxTextCtrl, wxComboBox, or wxComboCtrl" );
return nullptr;
}
bool SCH_NETNAME_VALIDATOR::Validate( wxWindow *aParent )
{
// If window is disabled, simply return
if ( !m_validatorWindow->IsEnabled() )
return true;
wxTextEntry * const text = GetTextEntry();
if ( !text )
return false;
const wxString& errormsg = IsValid( text->GetValue() );
if( !errormsg.empty() )
{
m_validatorWindow->SetFocus();
wxMessageBox( errormsg, _( "Invalid signal name" ), wxOK | wxICON_EXCLAMATION, aParent );
return false;
}
return true;
}
wxString SCH_NETNAME_VALIDATOR::IsValid( const wxString& str ) const wxString SCH_NETNAME_VALIDATOR::IsValid( const wxString& str ) const
{ {
if( NET_SETTINGS::ParseBusGroup( str, nullptr, nullptr ) ) if( NET_SETTINGS::ParseBusGroup( str, nullptr, nullptr ) )
@ -259,11 +193,5 @@ wxString SCH_NETNAME_VALIDATOR::IsValid( const wxString& str ) const
!NET_SETTINGS::ParseBusVector( str, nullptr, nullptr ) ) !NET_SETTINGS::ParseBusVector( str, nullptr, nullptr ) )
return _( "Signal name contains '[' or ']' but is not a valid vector bus name" ); return _( "Signal name contains '[' or ']' but is not a valid vector bus name" );
if( str.Contains( '\r' ) || str.Contains( '\n' ) ) return NETNAME_VALIDATOR::IsValid( str );
return _( "Signal names cannot contain CR or LF characters" );
if( !m_allowSpaces && ( str.Contains( ' ' ) || str.Contains( '\t' ) ) )
return _( "Signal names cannot contain spaces" );
return wxString();
} }

View File

@ -31,7 +31,7 @@
#define _SCH_VALIDATORS_H_ #define _SCH_VALIDATORS_H_
#include <wx/valtext.h> #include <wx/valtext.h>
#include <validators.h>
#define FIELD_NAME -1 #define FIELD_NAME -1
#define FIELD_VALUE -2 #define FIELD_VALUE -2
@ -71,38 +71,27 @@ public:
}; };
class SCH_NETNAME_VALIDATOR : public wxValidator /*
* A refinement of the NETNAME_VALIDATOR which also allows (and checks) bus definitions.
*/
class SCH_NETNAME_VALIDATOR : public NETNAME_VALIDATOR
{ {
public: public:
SCH_NETNAME_VALIDATOR( wxString *aVal = nullptr ); SCH_NETNAME_VALIDATOR( wxString *aVal = nullptr ) :
NETNAME_VALIDATOR( aVal )
{ }
SCH_NETNAME_VALIDATOR( bool aAllowSpaces ); SCH_NETNAME_VALIDATOR( bool aAllowSpaces ) :
NETNAME_VALIDATOR( aAllowSpaces )
{ }
SCH_NETNAME_VALIDATOR( const SCH_NETNAME_VALIDATOR& aValidator ); SCH_NETNAME_VALIDATOR( const SCH_NETNAME_VALIDATOR& aValidator ) :
NETNAME_VALIDATOR( aValidator )
void SetAllowSpaces( bool aAllowSpaces = true ) { m_allowSpaces = aAllowSpaces; } { }
bool GetAllowSpaces() const { return m_allowSpaces; }
bool Copy( const SCH_NETNAME_VALIDATOR& val );
virtual wxObject* Clone() const override { return new SCH_NETNAME_VALIDATOR( *this ); }
virtual bool TransferToWindow() override { return true; }
virtual bool TransferFromWindow() override { return true; }
wxTextEntry* GetTextEntry();
virtual bool Validate( wxWindow *aParent ) override;
protected: protected:
// returns the error message if the contents of 'val' are invalid // returns the error message if the contents of 'val' are invalid
virtual wxString IsValid( const wxString& aVal ) const; wxString IsValid( const wxString& aVal ) const override;
private:
bool m_allowSpaces;
}; };
#endif // _SCH_VALIDATORS_H_ #endif // _SCH_VALIDATORS_H_

View File

@ -1,12 +1,8 @@
/**
* @file eeschema/tools/backannotate.cpp
*/
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2019 Alexander Shuklin <Jasuramme@gmail.com> * Copyright (C) 2019 Alexander Shuklin <Jasuramme@gmail.com>
* Copyright (C) 2004-2019 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2004-2020 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -31,18 +27,25 @@
#include <boost/property_tree/ptree.hpp> #include <boost/property_tree/ptree.hpp>
#include <confirm.h> #include <confirm.h>
#include <dsnlexer.h> #include <dsnlexer.h>
#include <kiface_i.h>
#include <macros.h>
#include <ptree.h> #include <ptree.h>
#include <reporter.h> #include <reporter.h>
#include <sch_edit_frame.h> #include <sch_edit_frame.h>
#include <sch_sheet_path.h> #include <sch_sheet_path.h>
#include <schematic.h> #include <schematic.h>
#include <utf8.h> #include <kiface_i.h>
BACK_ANNOTATE::BACK_ANNOTATE( SCH_EDIT_FRAME* aFrame, SETTINGS aSettings ) : BACK_ANNOTATE::BACK_ANNOTATE( SCH_EDIT_FRAME* aFrame, REPORTER& aReporter,
m_settings( aSettings ), bool aProcessFootprints, bool aProcessValues,
bool aProcessReferences, bool aProcessNetNames,
bool aIgnoreOtherProjects, bool aDryRun ) :
m_reporter( aReporter ),
m_processFootprints( aProcessFootprints ),
m_processValues( aProcessValues ),
m_processReferences( aProcessReferences ),
m_processNetNames( aProcessNetNames ),
m_ignoreOtherProjects( aIgnoreOtherProjects ),
m_dryRun( aDryRun ),
m_frame( aFrame ), m_frame( aFrame ),
m_changesCount( 0 ) m_changesCount( 0 )
{ {
@ -59,103 +62,100 @@ bool BACK_ANNOTATE::BackAnnotateSymbols( const std::string& aNetlist )
m_changesCount = 0; m_changesCount = 0;
wxString msg; wxString msg;
if( !m_settings.processValues && !m_settings.processFootprints if( !m_processValues && !m_processFootprints && !m_processReferences && !m_processNetNames )
&& !m_settings.processReferences )
{ {
m_settings.reporter.ReportTail( m_reporter.ReportTail( _( "Select at least one property to back annotate." ),
_( "Select at least one property to back annotate" ), RPT_SEVERITY_ERROR ); RPT_SEVERITY_ERROR );
return false; return false;
} }
int errors = getPcbModulesFromString( aNetlist ); getPcbModulesFromString( aNetlist );
SCH_SHEET_LIST sheets = m_frame->Schematic().GetSheets(); SCH_SHEET_LIST sheets = m_frame->Schematic().GetSheets();
sheets.GetComponents( m_refs, false ); sheets.GetComponents( m_refs, false );
sheets.GetMultiUnitComponents( m_multiUnitsRefs ); sheets.GetMultiUnitComponents( m_multiUnitsRefs );
errors += getChangeList(); getChangeList();
errors += checkForUnusedSymbols(); checkForUnusedSymbols();
errors += checkSharedSchematicErrors(); checkSharedSchematicErrors();
if( errors > 0 ) SCH_SHEET_PATH current = m_frame->GetCurrentSheet();
m_settings.dryRun = true;
applyChangelist(); applyChangelist();
m_frame->SetCurrentSheet( current );
if( !errors ) return true;
{
if( !m_settings.dryRun )
{
msg.Printf( _( "Schematic is back-annotated. %d changes applied." ), m_changesCount );
m_settings.reporter.ReportTail( msg, RPT_SEVERITY_ACTION );
}
else
m_settings.reporter.ReportTail(
_( "No errors during dry run. Ready to go." ), RPT_SEVERITY_ACTION );
}
else
{
msg.Printf( _( "Found %d errors. Fix them and run back annotation." ), errors );
m_settings.reporter.ReportTail( msg, RPT_SEVERITY_ERROR );
}
return !errors;
} }
bool BACK_ANNOTATE::FetchNetlistFromPCB( std::string& aNetlist ) bool BACK_ANNOTATE::FetchNetlistFromPCB( std::string& aNetlist )
{ {
if( Kiface().IsSingle() ) if( Kiface().IsSingle() )
{ {
DisplayErrorMessage( DisplayErrorMessage( m_frame, _( "Cannot fetch PCB netlist because eeschema is opened "
m_frame, _( "Cannot fetch PCB netlist because eeschema is opened in " "in stand-alone mode.\n"
"stand-alone mode.\n" "You must launch the KiCad project manager and create "
"You must launch the KiCad project manager " "a project." ) );
"and create a project." ) );
return false;
}
KIWAY_PLAYER* player = m_frame->Kiway().Player( FRAME_PCB_EDITOR, false );
if( !player )
{
DisplayErrorMessage(
this->m_frame, _( "Please open Pcbnew and run back annotation again" ) );
return false; return false;
} }
m_frame->Kiway().Player( FRAME_PCB_EDITOR, true );
m_frame->Kiway().ExpressMail( FRAME_PCB_EDITOR, MAIL_PCB_GET_NETLIST, aNetlist ); m_frame->Kiway().ExpressMail( FRAME_PCB_EDITOR, MAIL_PCB_GET_NETLIST, aNetlist );
return true; return true;
} }
int BACK_ANNOTATE::getPcbModulesFromString( const std::string& aPayload ) void BACK_ANNOTATE::getPcbModulesFromString( const std::string& aPayload )
{ {
auto getStr = []( const PTREE& pt ) -> wxString
{
return UTF8( pt.front().first );
};
DSNLEXER lexer( aPayload, FROM_UTF8( __func__ ) ); DSNLEXER lexer( aPayload, FROM_UTF8( __func__ ) );
PTREE doc; PTREE doc;
Scan( &doc, &lexer );
CPTREE& tree = doc.get_child( "pcb_netlist" );
wxString msg;
int errors = 0; // NOTE: KiCad's PTREE scanner constructs a property *name* tree, not a property tree.
// Every token in the s-expr is stored as a property name; the property's value is then
// either the nested s-exprs or an empty PTREE; there are *no* literal property values.
Scan( &doc, &lexer );
PTREE& tree = doc.get_child( "pcb_netlist" );
wxString msg;
m_pcbModules.clear(); m_pcbModules.clear();
for( auto& item : tree )
for( const std::pair<const std::string, PTREE>& item : tree )
{ {
wxString path, value, footprint; wxString path, value, footprint;
std::map<wxString, wxString> pinNetMap;
wxASSERT( item.first == "ref" ); wxASSERT( item.first == "ref" );
wxString ref = UTF8( item.second.front().first ); wxString ref = getStr( item.second );
try try
{ {
path = UTF8( item.second.get_child( "timestamp" ).front().first ); path = getStr( item.second.get_child( "timestamp" ) );
if( path == "" ) if( path == "" )
{ {
msg.Printf( _( "Footprint \"%s\" has no symbol associated." ), ref ); msg.Printf( _( "Footprint \"%s\" has no symbol associated." ), ref );
m_settings.reporter.ReportHead( msg, RPT_SEVERITY_WARNING ); m_reporter.ReportHead( msg, RPT_SEVERITY_WARNING );
continue; continue;
} }
footprint = UTF8( item.second.get_child( "fpid" ).front().first );
value = UTF8( item.second.get_child( "value" ).front().first ); footprint = getStr( item.second.get_child( "fpid" ) );
value = getStr( item.second.get_child( "value" ) );
boost::optional<const PTREE&> nets = item.second.get_child_optional( "nets" );
if( nets )
{
for( const std::pair<const std::string, PTREE>& pin_net : nets.get() )
{
wxASSERT( pin_net.first == "pin_net" );
wxString pinNumber = UTF8( pin_net.second.front().first );
wxString netName = UTF8( pin_net.second.back().first );
pinNetMap[ pinNumber ] = netName;
}
}
} }
catch( ... ) catch( ... )
{ {
@ -169,34 +169,30 @@ int BACK_ANNOTATE::getPcbModulesFromString( const std::string& aPayload )
{ {
// Module with this path already exists - generate error // Module with this path already exists - generate error
msg.Printf( _( "Pcb footprints \"%s\" and \"%s\" linked to same symbol" ), msg.Printf( _( "Pcb footprints \"%s\" and \"%s\" linked to same symbol" ),
nearestItem->second->ref, ref ); nearestItem->second->m_ref, ref );
m_settings.reporter.ReportHead( msg, RPT_SEVERITY_ERROR ); m_reporter.ReportHead( msg, RPT_SEVERITY_ERROR );
++errors;
} }
else else
{ {
// Add module to the map // Add module to the map
PCB_MODULE_DATA data( ref, footprint, value ); auto data = std::make_shared<PCB_MODULE_DATA>( ref, footprint, value, pinNetMap );
m_pcbModules.insert( nearestItem, m_pcbModules.insert( nearestItem, std::make_pair( path, data ) );
std::make_pair( path, std::make_shared<PCB_MODULE_DATA>( data ) ) );
} }
} }
return errors;
} }
int BACK_ANNOTATE::getChangeList()
{
int errors = 0;
for( auto& module : m_pcbModules ) void BACK_ANNOTATE::getChangeList()
{
for( std::pair<const wxString, std::shared_ptr<PCB_MODULE_DATA>>& module : m_pcbModules )
{ {
auto& pcbPath = module.first; const wxString& pcbPath = module.first;
auto& pcbData = module.second; auto& pcbData = module.second;
bool foundInMultiunit = false; bool foundInMultiunit = false;
for( auto& item : m_multiUnitsRefs ) for( auto& item : m_multiUnitsRefs )
{ {
auto& refList = item.second; SCH_REFERENCE_LIST& refList = item.second;
if( refList.FindRefByPath( pcbPath ) >= 0 ) if( refList.FindRefByPath( pcbPath ) >= 0 )
{ {
@ -206,8 +202,10 @@ int BACK_ANNOTATE::getChangeList()
foundInMultiunit = true; foundInMultiunit = true;
for( size_t i = 0; i < refList.GetCount(); ++i ) for( size_t i = 0; i < refList.GetCount(); ++i )
{ {
m_changelist.push_back( CHANGELIST_ITEM( refList[i], pcbData ) ); refList[i].GetComp()->ClearFlags( SKIP_STRUCT );
m_changelist.emplace_back( CHANGELIST_ITEM( refList[i], pcbData ) );
} }
break; break;
} }
} }
@ -218,23 +216,22 @@ int BACK_ANNOTATE::getChangeList()
int refIndex = m_refs.FindRefByPath( pcbPath ); int refIndex = m_refs.FindRefByPath( pcbPath );
if( refIndex >= 0 ) if( refIndex >= 0 )
m_changelist.push_back( CHANGELIST_ITEM( m_refs[refIndex], pcbData ) ); {
m_refs[refIndex].GetComp()->ClearFlags( SKIP_STRUCT );
m_changelist.emplace_back( CHANGELIST_ITEM( m_refs[refIndex], pcbData ) );
}
else else
{ {
// Haven't found linked symbol in multiunits or common refs. Generate error // Haven't found linked symbol in multiunits or common refs. Generate error
wxString msg; wxString msg;
msg.Printf( _( "Cannot find symbol for \"%s\" footprint" ), pcbData->ref ); msg.Printf( _( "Cannot find symbol for \"%s\" footprint" ), pcbData->m_ref );
++errors; m_reporter.ReportTail( msg, RPT_SEVERITY_ERROR );
m_settings.reporter.ReportTail( msg, RPT_SEVERITY_ERROR );
} }
} }
return errors;
} }
int BACK_ANNOTATE::checkForUnusedSymbols() void BACK_ANNOTATE::checkForUnusedSymbols()
{ {
int errors = 0;
m_refs.SortByTimeStamp(); m_refs.SortByTimeStamp();
std::sort( m_changelist.begin(), m_changelist.end(), std::sort( m_changelist.begin(), m_changelist.end(),
@ -244,32 +241,31 @@ int BACK_ANNOTATE::checkForUnusedSymbols()
} ); } );
size_t i = 0; size_t i = 0;
for( auto& item : m_changelist ) for( auto& item : m_changelist )
{ {
// Refs and changelist are both sorted by paths, so we just go over m_refs and // Refs and changelist are both sorted by paths, so we just go over m_refs and
// generate errors before we will find m_refs member to which item linked // generate errors before we will find m_refs member to which item linked
while( i < m_refs.GetCount() && m_refs[i].GetPath() != item.first.GetPath() ) while( i < m_refs.GetCount() && m_refs[i].GetPath() != item.first.GetPath() )
{ {
++errors;
wxString msg; wxString msg;
msg.Printf( _( "Cannot find footprint for \"%s\" symbol" ), m_refs[i++].GetFullRef() ); msg.Printf( _( "Cannot find footprint for \"%s\" symbol" ), m_refs[i++].GetFullRef() );
m_settings.reporter.ReportTail( msg, RPT_SEVERITY_ERROR ); m_reporter.ReportTail( msg, RPT_SEVERITY_ERROR );
} }
++i; ++i;
} }
return errors;
} }
bool BACK_ANNOTATE::checkReuseViolation( PCB_MODULE_DATA& aFirst, PCB_MODULE_DATA& aSecond ) bool BACK_ANNOTATE::checkReuseViolation( PCB_MODULE_DATA& aFirst, PCB_MODULE_DATA& aSecond )
{ {
if( m_processFootprints && aFirst.m_footprint != aSecond.m_footprint )
if( m_settings.processFootprints && aFirst.footprint != aSecond.footprint )
return false; return false;
if( m_settings.processValues && aFirst.value != aSecond.value ) if( m_processValues && aFirst.m_value != aSecond.m_value )
return false; return false;
return true; return true;
} }
@ -279,18 +275,17 @@ wxString BACK_ANNOTATE::getTextFromField( const SCH_REFERENCE& aRef, const NumFi
} }
int BACK_ANNOTATE::checkSharedSchematicErrors() void BACK_ANNOTATE::checkSharedSchematicErrors()
{ {
std::sort( m_changelist.begin(), m_changelist.end(), std::sort( m_changelist.begin(), m_changelist.end(),
[]( CHANGELIST_ITEM& a, CHANGELIST_ITEM& b ) { []( CHANGELIST_ITEM& a, CHANGELIST_ITEM& b )
return a.first.GetComp() > b.first.GetComp(); {
} ); return a.first.GetComp() > b.first.GetComp();
} );
// We don't check that if no footprints or values updating // We don't check that if no footprints or values updating
if( !m_settings.processFootprints && !m_settings.processValues ) if( !m_processFootprints && !m_processValues )
return 0; return;
int errors = 0;
// We will count how many times every component used in our changelist // We will count how many times every component used in our changelist
// Component in this case is SCH_COMPONENT which can be used by more than one symbol // Component in this case is SCH_COMPONENT which can be used by more than one symbol
@ -307,90 +302,302 @@ int BACK_ANNOTATE::checkSharedSchematicErrors()
if( ( it + 1 ) != m_changelist.end() && it->first.GetComp() == ( it + 1 )->first.GetComp() ) if( ( it + 1 ) != m_changelist.end() && it->first.GetComp() == ( it + 1 )->first.GetComp() )
{ {
++usageCount; ++usageCount;
if( !checkReuseViolation( *it->second, *( it + 1 )->second ) ) if( !checkReuseViolation( *it->second, *( it + 1 )->second ) )
{ {
// Refs share same component but have different values or footprints // Refs share same component but have different values or footprints
++errors; it->first.GetComp()->SetFlags( SKIP_STRUCT );
wxString msg; wxString msg;
msg.Printf( _( "\"%s\" and \"%s\" use the same schematic symbol.\n" msg.Printf( _( "\"%s\" and \"%s\" use the same schematic symbol.\n"
"They cannot have different footprints or values." ), "They cannot have different footprints or values." ),
( it + 1 )->second->ref, it->second->ref ); ( it + 1 )->second->m_ref,
m_settings.reporter.ReportTail( msg, RPT_SEVERITY_ERROR ); it->second->m_ref );
m_reporter.ReportTail( msg, RPT_SEVERITY_ERROR );
} }
} }
else else
{ {
/* Next ref uses different component, so we count all components number for current /* Next ref uses different component, so we count all components number for current
one. We compare that number to stored in the component itself. If that differs, it one. We compare that number to stored in the component itself. If that differs, it
means that this particular component is reused in some another project. */ means that this particular component is reused in some other project. */
if( !m_settings.ignoreOtherProjects && compUsage > usageCount ) if( !m_ignoreOtherProjects && compUsage > usageCount )
{ {
PCB_MODULE_DATA tmp{ "", getTextFromField( it->first, FOOTPRINT ), PCB_MODULE_DATA tmp{ "",
getTextFromField( it->first, VALUE ) }; getTextFromField( it->first, FOOTPRINT ),
getTextFromField( it->first, VALUE ),
{} };
if( !checkReuseViolation( tmp, *it->second ) ) if( !checkReuseViolation( tmp, *it->second ) )
{ {
it->first.GetComp()->SetFlags( SKIP_STRUCT );
wxString msg; wxString msg;
msg.Printf( _( "Unable to change \"%s\" footprint or value because associated" msg.Printf( _( "Unable to change \"%s\" footprint or value because associated"
" symbol is reused in the another project" ), " symbol is reused in the another project" ),
it->second->ref ); it->second->m_ref );
m_settings.reporter.ReportTail( msg, RPT_SEVERITY_ERROR ); m_reporter.ReportTail( msg, RPT_SEVERITY_ERROR );
++errors;
} }
} }
usageCount = 1; usageCount = 1;
} }
} }
return errors;
} }
void BACK_ANNOTATE::applyChangelist() void BACK_ANNOTATE::applyChangelist()
{ {
wxString msg; std::set<wxString> handledNetChanges;
int leftUnchanged = 0; wxString msg;
int leftUnchanged = 0;
// Apply changes from change list // Apply changes from change list
for( auto& item : m_changelist ) for( CHANGELIST_ITEM& item : m_changelist )
{ {
SCH_REFERENCE& ref = item.first; SCH_REFERENCE& ref = item.first;
PCB_MODULE_DATA& module = *item.second; PCB_MODULE_DATA& module = *item.second;
wxString oldFootprint = getTextFromField( ref, FOOTPRINT ); wxString oldFootprint = getTextFromField( ref, FOOTPRINT );
wxString oldValue = getTextFromField( ref, VALUE ); wxString oldValue = getTextFromField( ref, VALUE );
int changesCountBefore = m_changesCount; int changesCountBefore = m_changesCount;
bool skip = ( ref.GetComp()->GetFlags() & SKIP_STRUCT ) > 0;
if( m_settings.processReferences && ref.GetRef() != module.ref ) if( m_processReferences && ref.GetRef() != module.m_ref && !skip )
{ {
++m_changesCount; ++m_changesCount;
msg.Printf( _( "Change \"%s\" reference designator to \"%s\"." ), ref.GetFullRef(), module.ref ); msg.Printf( _( "Change \"%s\" reference designator to \"%s\"." ),
if( !m_settings.dryRun ) ref.GetFullRef(),
ref.GetComp()->SetRef( &ref.GetSheetPath(), module.ref ); module.m_ref );
m_settings.reporter.ReportHead( msg, RPT_SEVERITY_ACTION );
if( !m_dryRun )
ref.GetComp()->SetRef( &ref.GetSheetPath(), module.m_ref );
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION );
} }
if( m_settings.processFootprints && oldFootprint != module.footprint ) if( m_processFootprints && oldFootprint != module.m_footprint && !skip )
{ {
++m_changesCount; ++m_changesCount;
msg.Printf( _( "Change %s footprint from \"%s\" to \"%s\"." ), ref.GetFullRef(), msg.Printf( _( "Change %s footprint from \"%s\" to \"%s\"." ),
getTextFromField( ref, FOOTPRINT ), module.footprint ); ref.GetFullRef(),
getTextFromField( ref, FOOTPRINT ),
module.m_footprint );
if( !m_settings.dryRun ) if( !m_dryRun )
ref.GetComp()->GetField( FOOTPRINT )->SetText( module.footprint ); ref.GetComp()->GetField( FOOTPRINT )->SetText( module.m_footprint );
m_settings.reporter.ReportHead( msg, RPT_SEVERITY_ACTION );
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION );
} }
if( m_settings.processValues && oldValue != module.value ) if( m_processValues && oldValue != module.m_value && !skip )
{ {
++m_changesCount; ++m_changesCount;
msg.Printf( _( "Change \"%s\" value from \"%s\" to \"\"%s\"." ), ref.GetFullRef(), msg.Printf( _( "Change %s value from \"%s\" to \"%s\"." ),
getTextFromField( ref, VALUE ), module.value ); ref.GetFullRef(),
if( !m_settings.dryRun ) getTextFromField( ref, VALUE ),
item.first.GetComp()->GetField( VALUE )->SetText( module.value ); module.m_value );
m_settings.reporter.ReportHead( msg, RPT_SEVERITY_ACTION );
if( !m_dryRun )
item.first.GetComp()->GetField( VALUE )->SetText( module.m_value );
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION );
}
if( m_processNetNames )
{
for( const std::pair<const wxString, wxString>& entry : module.m_pinMap )
{
const wxString& pinNumber = entry.first;
const wxString& shortNetName = entry.second;
SCH_COMPONENT* comp = ref.GetComp();
LIB_PIN* pin = comp->GetPin( pinNumber );
SCH_CONNECTION* conn = comp->GetConnectionForPin( pin, ref.GetSheetPath() );
wxString key = shortNetName + ref.GetSheetPath().PathAsString();
if( handledNetChanges.count( key ) )
continue;
else
handledNetChanges.insert( key );
if( conn && conn->Name( true ) != shortNetName )
processNetNameChange( conn, conn->Name( true ), shortNetName );
}
} }
if( changesCountBefore == m_changesCount ) if( changesCountBefore == m_changesCount )
++leftUnchanged; ++leftUnchanged;
} }
msg.Printf( _( "%d symbols left unchanged" ), leftUnchanged ); msg.Printf( _( "%d symbols left unchanged" ), leftUnchanged );
m_settings.reporter.ReportHead( msg, RPT_SEVERITY_INFO ); m_reporter.ReportHead( msg, RPT_SEVERITY_INFO );
} }
void BACK_ANNOTATE::processNetNameChange( SCH_CONNECTION* aConn, const wxString& aOldName,
const wxString& aNewName )
{
wxString msg;
SCH_ITEM* driver = aConn->Driver();
auto editMatchingLabels =
[this]( SCH_SCREEN* aScreen, KICAD_T aType, const wxString& oldName,
const wxString& newName )
{
for( SCH_ITEM* schItem : aScreen->Items().OfType( aType ) )
{
SCH_TEXT* label = static_cast<SCH_TEXT*>( schItem );
if( EscapeString( label->GetShownText(), CTX_NETNAME ) == oldName )
{
m_frame->SaveCopyInUndoList( label, UR_CHANGED );
static_cast<SCH_TEXT*>( label )->SetText( newName );
}
}
};
switch( driver->Type() )
{
case SCH_LABEL_T:
++m_changesCount;
msg.Printf( _( "Change \"%s\" labels to \"%s\"." ),
aOldName,
aNewName );
if( !m_dryRun )
{
m_frame->Schematic().SetCurrentSheet( aConn->Sheet() );
for( SCH_ITEM* label : m_frame->GetScreen()->Items().OfType( SCH_LABEL_T ) )
{
SCH_CONNECTION* conn = label->Connection( aConn->Sheet() );
if( conn && conn->Driver() == driver )
{
m_frame->SaveCopyInUndoList( label, UR_CHANGED );
static_cast<SCH_TEXT*>( label )->SetText( aNewName );
}
}
}
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION );
break;
case SCH_GLOBAL_LABEL_T:
++m_changesCount;
msg.Printf( _( "Change \"%s\" global labels to \"%s\"." ),
aConn->Name( true ),
aNewName );
if( !m_dryRun )
{
SCH_SHEET_LIST all_sheets = m_frame->Schematic().GetSheets();
for( const SCH_SHEET_PATH& sheet : all_sheets )
{
m_frame->Schematic().SetCurrentSheet( sheet );
editMatchingLabels( m_frame->GetScreen(), SCH_GLOBAL_LABEL_T, aOldName, aNewName );
}
}
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION );
break;
case SCH_HIER_LABEL_T:
++m_changesCount;
msg.Printf( _( "Change \"%s\" hierarchical label to \"%s\"." ),
aConn->Name( true ),
aNewName );
if( !m_dryRun )
{
m_frame->Schematic().SetCurrentSheet( aConn->Sheet() );
editMatchingLabels( m_frame->GetScreen(), SCH_HIER_LABEL_T, aOldName, aNewName );
SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( driver->GetParent() );
m_frame->SetScreen( sheet->GetScreen() );
for( SCH_SHEET_PIN* pin : sheet->GetPins() )
{
if( EscapeString( pin->GetShownText(), CTX_NETNAME ) == aOldName )
{
m_frame->SaveCopyInUndoList( pin, UR_CHANGED );
static_cast<SCH_TEXT*>( pin )->SetText( aNewName );
}
}
}
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION );
break;
case SCH_SHEET_PIN_T:
++m_changesCount;
msg.Printf( _( "Change \"%s\" hierarchical label to \"%s\"." ),
aConn->Name( true ),
aNewName );
if( !m_dryRun )
{
m_frame->Schematic().SetCurrentSheet( aConn->Sheet() );
m_frame->SaveCopyInUndoList( driver, UR_CHANGED );
static_cast<SCH_TEXT*>( driver )->SetText( aNewName );
SCH_SHEET* sheet = static_cast<SCH_SHEET_PIN*>( driver )->GetParent();
m_frame->SetScreen( sheet->GetScreen() );
editMatchingLabels( sheet->GetScreen(), SCH_HIER_LABEL_T, aOldName, aNewName );
}
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION );
break;
case LIB_PIN_T:
{
LIB_PIN* pin = dynamic_cast<LIB_PIN*>( driver );
LABEL_SPIN_STYLE spin = LABEL_SPIN_STYLE::RIGHT;
if( pin->IsPowerConnection() )
{
msg.Printf( _( "Net \"%s\" cannot be changed to \"%s\" because it "
"is driven by a power pin." ),
aOldName,
aNewName );
m_reporter.ReportHead( msg, RPT_SEVERITY_ERROR );
break;
}
switch( pin->GetOrientation() )
{
case PIN_UP: spin = LABEL_SPIN_STYLE::UP; break;
case PIN_DOWN: spin = LABEL_SPIN_STYLE::BOTTOM; break;
case PIN_LEFT: spin = LABEL_SPIN_STYLE::LEFT; break;
case PIN_RIGHT: spin = LABEL_SPIN_STYLE::RIGHT; break;
}
++m_changesCount;
msg.Printf( _( "Add label \"%s\" to net \"%s\"." ),
aNewName,
aConn->Name( true ) );
if( !m_dryRun )
{
SCHEMATIC_SETTINGS& settings = m_frame->Schematic().Settings();
SCH_LABEL* label = new SCH_LABEL( driver->GetPosition(), aNewName );
label->SetParent( &m_frame->Schematic() );
label->SetTextSize( wxSize( settings.m_DefaultTextSize,
settings.m_DefaultTextSize ) );
label->SetLabelSpinStyle( spin );
label->SetFlags( IS_NEW );
m_frame->Schematic().SetCurrentSheet( aConn->Sheet() );
m_frame->AddItemToScreenAndUndoList( label );
}
m_reporter.ReportHead( msg, RPT_SEVERITY_ACTION );
}
break;
default:
break;
}
m_frame->Schematic().SetCurrentSheet( SCH_SHEET_PATH() );
}

View File

@ -1,12 +1,8 @@
/**
* @file eeschema/tools/backannotate.h
*/
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2019 Alexander Shuklin <Jasuramme@gmail.com> * Copyright (C) 2019 Alexander Shuklin <Jasuramme@gmail.com>
* Copyright (C) 2004-2019 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2004-2020 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -44,8 +40,9 @@ class SCH_EDIT_FRAME;
/** /**
* @brief Back annotation algorithm class. It used to recieve, check and apply \ref NETLIST * @brief Back annotation algorithm class used to recieve, check, and apply a \ref NETLIST from
* from PCBNEW. Class check for following collisions: * PCBNEW.
* The following checks are made:
* - Schematic symbol exists, but linked PCBnew module missing * - Schematic symbol exists, but linked PCBnew module missing
* - PCBnew module exists but no schematic symbol connected to * - PCBnew module exists but no schematic symbol connected to
* - PCBnew module is standalone * - PCBnew module is standalone
@ -58,31 +55,23 @@ class SCH_EDIT_FRAME;
class BACK_ANNOTATE class BACK_ANNOTATE
{ {
public: public:
/**
* @brief settings struct to set up back annotation
*/
struct SETTINGS
{
REPORTER& reporter;
bool processFootprints;
bool processValues;
bool processReferences;
bool ignoreOtherProjects;
bool dryRun;
};
/** /**
* @brief Struct to hold PCBnew module data * @brief Struct to hold PCBnew module data
*/ */
struct PCB_MODULE_DATA struct PCB_MODULE_DATA
{ {
PCB_MODULE_DATA(wxString aRef, wxString aFootprint, wxString aValue) : PCB_MODULE_DATA( const wxString& aRef, const wxString& aFootprint,
ref(aRef), const wxString& aValue, const std::map<wxString, wxString> aPinMap ) :
footprint(aFootprint), m_ref( aRef ),
value(aValue){}; m_footprint( aFootprint ),
wxString ref; m_value( aValue ),
wxString footprint; m_pinMap( aPinMap )
wxString value; {};
wxString m_ref;
wxString m_footprint;
wxString m_value;
std::map<wxString, wxString> m_pinMap;
}; };
///> Map to hold NETLIST modules data ///> Map to hold NETLIST modules data
@ -90,11 +79,9 @@ public:
using CHANGELIST_ITEM = std::pair<SCH_REFERENCE, std::shared_ptr<PCB_MODULE_DATA>>; using CHANGELIST_ITEM = std::pair<SCH_REFERENCE, std::shared_ptr<PCB_MODULE_DATA>>;
///> To hold match between reference and PCBnew module BACK_ANNOTATE( SCH_EDIT_FRAME* aFrame, REPORTER& aReporter, bool aProcessFootprints,
using CHANGELIST = std::deque<CHANGELIST_ITEM>; bool aProcessValues, bool aProcessReferences, bool aProcessNetNames,
bool aIgnoreOtherProjects, bool aDryRun );
BACK_ANNOTATE( SCH_EDIT_FRAME* aFrame, SETTINGS aSettings );
~BACK_ANNOTATE(); ~BACK_ANNOTATE();
/** /**
@ -113,11 +100,19 @@ public:
bool BackAnnotateSymbols( const std::string& aNetlist ); bool BackAnnotateSymbols( const std::string& aNetlist );
private: private:
SETTINGS m_settings; REPORTER& m_reporter;
bool m_processFootprints;
bool m_processValues;
bool m_processReferences;
bool m_processNetNames;
bool m_ignoreOtherProjects;
bool m_dryRun;
PCB_MODULES_MAP m_pcbModules; PCB_MODULES_MAP m_pcbModules;
SCH_REFERENCE_LIST m_refs; SCH_REFERENCE_LIST m_refs;
SCH_MULTI_UNIT_REFERENCE_MAP m_multiUnitsRefs; SCH_MULTI_UNIT_REFERENCE_MAP m_multiUnitsRefs;
CHANGELIST m_changelist; std::deque<CHANGELIST_ITEM> m_changelist;
SCH_EDIT_FRAME* m_frame; SCH_EDIT_FRAME* m_frame;
///> To count number of changes applied to the schematic ///> To count number of changes applied to the schematic
@ -140,28 +135,29 @@ private:
* @param aPayload - netlist from PCBnew * @param aPayload - netlist from PCBnew
* @return number of errors during parsing * @return number of errors during parsing
*/ */
int getPcbModulesFromString( const std::string& aPayload ); void getPcbModulesFromString( const std::string& aPayload );
///> Create changelist ///> Create changelist
int getChangeList(); void getChangeList();
/** /**
* @brief Check if some symbols are not represented in PCB modules and vice versa. * @brief Check if some symbols are not represented in PCB modules and vice versa.
* \ref m_refs must be sorted by path * \ref m_refs must be sorted by path
* @return number of errors
*/ */
int checkForUnusedSymbols(); void checkForUnusedSymbols();
/** /**
* @brief Check for errors connected to reusing schematic in project or between projects * @brief Check for errors connected to reusing schematic in project or between projects
* @return number of errors
*/ */
int checkSharedSchematicErrors(); void checkSharedSchematicErrors();
/** /**
* @brief Apply changelist to the schematic * @brief Apply changelist to the schematic
*/ */
void applyChangelist(); void applyChangelist();
void processNetNameChange( SCH_CONNECTION* aConn, const wxString& aOldName,
const wxString& aNewName );
}; };
#endif #endif

View File

@ -194,6 +194,33 @@ protected:
LIB_ID::LIB_ID_TYPE m_idType; LIB_ID::LIB_ID_TYPE m_idType;
}; };
class NETNAME_VALIDATOR : public wxTextValidator
{
public:
NETNAME_VALIDATOR( wxString *aVal = nullptr );
NETNAME_VALIDATOR( bool aAllowSpaces );
NETNAME_VALIDATOR( const NETNAME_VALIDATOR& aValidator );
virtual wxObject* Clone() const override { return new NETNAME_VALIDATOR( *this ); }
virtual bool TransferToWindow() override { return true; }
virtual bool TransferFromWindow() override { return true; }
virtual bool Validate( wxWindow *aParent ) override;
protected:
// returns the error message if the contents of 'val' are invalid
wxString IsValid( const wxString& aVal ) const override;
private:
bool m_allowSpaces;
};
namespace KIUI namespace KIUI
{ {
/** /**

View File

@ -34,7 +34,6 @@
#include <class_board.h> #include <class_board.h>
#include <class_module.h> #include <class_module.h>
#include <class_track.h> #include <class_track.h>
#include <class_zone.h>
#include <collectors.h> #include <collectors.h>
#include <eda_dde.h> #include <eda_dde.h>
#include <fctsys.h> #include <fctsys.h>
@ -43,14 +42,10 @@
#include <macros.h> #include <macros.h>
#include <netlist_reader/pcb_netlist.h> #include <netlist_reader/pcb_netlist.h>
#include <pcb_edit_frame.h> #include <pcb_edit_frame.h>
#include <pcb_painter.h>
#include <pcbnew.h>
#include <pcbnew_settings.h> #include <pcbnew_settings.h>
#include <pgm_base.h>
#include <tool/tool_manager.h> #include <tool/tool_manager.h>
#include <tools/pcb_actions.h> #include <tools/pcb_actions.h>
#include <tools/selection_tool.h> #include <tools/selection_tool.h>
#include <wx/tokenzr.h>
/* Execute a remote command send by Eeschema via a socket, /* Execute a remote command send by Eeschema via a socket,
* port KICAD_PCB_PORT_SERVICE_NUMBER * port KICAD_PCB_PORT_SERVICE_NUMBER
@ -402,13 +397,24 @@ void PCB_EDIT_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
{ {
NETLIST netlist; NETLIST netlist;
STRING_FORMATTER sf; STRING_FORMATTER sf;
for( auto& module : this->GetBoard()->Modules() )
for( MODULE* module : this->GetBoard()->Modules() )
{ {
netlist.AddComponent( new COMPONENT( module->GetFPID(), module->GetReference(), COMPONENT* component = new COMPONENT( module->GetFPID(), module->GetReference(),
module->GetValue(), module->GetPath() ) ); module->GetValue(), module->GetPath() );
for( D_PAD* pad : module->Pads() )
{
const wxString& netname = pad->GetShortNetname();
if( !netname.IsEmpty() )
component->AddNet( pad->GetName(), netname, wxEmptyString );
}
netlist.AddComponent( component );
} }
netlist.Format(
"pcb_netlist", &sf, 0, CTL_OMIT_FILTERS | CTL_OMIT_NETS | CTL_OMIT_FILTERS ); netlist.Format( "pcb_netlist", &sf, 0, CTL_OMIT_FILTERS );
payload = sf.GetString(); payload = sf.GetString();
break; break;
} }

View File

@ -3,7 +3,7 @@
* *
* Copyright (C) 2020 Oleg Endo <olegendo@gcc.gnu.org> * Copyright (C) 2020 Oleg Endo <olegendo@gcc.gnu.org>
* Copyright (C) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -24,19 +24,18 @@
*/ */
#include <fctsys.h> #include <fctsys.h>
#include <kicad_string.h>
#include <pcbnew.h>
#include <tools/pcb_inspection_tool.h> #include <tools/pcb_inspection_tool.h>
#include <class_board.h> #include <class_board.h>
#include <class_track.h> #include <class_track.h>
#include <dialog_select_net_from_list.h> #include <dialog_select_net_from_list.h>
#include <eda_pattern_match.h> #include <eda_pattern_match.h>
#include <wildcards_and_files_ext.h> #include <wildcards_and_files_ext.h>
#include <view/view.h>
#include <view/view_controls.h> #include <view/view_controls.h>
#include <pcb_painter.h> #include <pcb_painter.h>
#include <connectivity/connectivity_data.h>
#include <connectivity/connectivity_algo.h> #include <connectivity/connectivity_algo.h>
#include <dialogs/dialog_text_entry.h>
#include <validators.h>
#include <bitmaps.h>
struct DIALOG_SELECT_NET_FROM_LIST::COLUMN_ID struct DIALOG_SELECT_NET_FROM_LIST::COLUMN_ID
{ {
@ -122,27 +121,23 @@ struct DIALOG_SELECT_NET_FROM_LIST::ROW_DESC
}; };
DIALOG_SELECT_NET_FROM_LIST::DIALOG_SELECT_NET_FROM_LIST( DIALOG_SELECT_NET_FROM_LIST::DIALOG_SELECT_NET_FROM_LIST( PCB_EDIT_FRAME* aParent,
PCB_EDIT_FRAME* aParent, const SETTINGS& aSettings ) const SETTINGS& aSettings ) :
: DIALOG_SELECT_NET_FROM_LIST_BASE( aParent ), m_frame( aParent ) DIALOG_SELECT_NET_FROM_LIST_BASE( aParent ),
m_frame( aParent )
{ {
m_brd = aParent->GetBoard(); m_brd = aParent->GetBoard();
m_wasSelected = false; m_wasSelected = false;
m_netsList->AppendTextColumn( #define ADD_COL( name, flag, align ) m_netsList->AppendTextColumn( name, flag, 0, align, 0 );
COLUMN_NET.display_name, wxDATAVIEW_CELL_INERT, 0, wxALIGN_LEFT, 0 );
m_netsList->AppendTextColumn( ADD_COL( COLUMN_NET.display_name, wxDATAVIEW_CELL_INERT, wxALIGN_LEFT );
COLUMN_NAME.display_name, wxDATAVIEW_CELL_INERT, 0, wxALIGN_LEFT, 0 ); ADD_COL( COLUMN_NAME.display_name, wxDATAVIEW_CELL_INERT, wxALIGN_LEFT );
m_netsList->AppendTextColumn( ADD_COL( COLUMN_PAD_COUNT.display_name, wxDATAVIEW_CELL_INERT, wxALIGN_CENTER );
COLUMN_PAD_COUNT.display_name, wxDATAVIEW_CELL_INERT, 0, wxALIGN_CENTER, 0 ); ADD_COL( COLUMN_VIA_COUNT.display_name, wxDATAVIEW_CELL_INERT, wxALIGN_CENTER );
m_netsList->AppendTextColumn( ADD_COL( COLUMN_BOARD_LENGTH.display_name, wxDATAVIEW_CELL_INERT, wxALIGN_CENTER );
COLUMN_VIA_COUNT.display_name, wxDATAVIEW_CELL_INERT, 0, wxALIGN_CENTER, 0 ); ADD_COL( COLUMN_CHIP_LENGTH.display_name, wxDATAVIEW_CELL_INERT, wxALIGN_CENTER );
m_netsList->AppendTextColumn( ADD_COL( COLUMN_TOTAL_LENGTH.display_name, wxDATAVIEW_CELL_INERT, wxALIGN_CENTER );
COLUMN_BOARD_LENGTH.display_name, wxDATAVIEW_CELL_INERT, 0, wxALIGN_CENTER, 0 );
m_netsList->AppendTextColumn(
COLUMN_CHIP_LENGTH.display_name, wxDATAVIEW_CELL_INERT, 0, wxALIGN_CENTER, 0 );
m_netsList->AppendTextColumn(
COLUMN_TOTAL_LENGTH.display_name, wxDATAVIEW_CELL_INERT, 0, wxALIGN_CENTER, 0 );
// The fact that we're a list should keep the control from reserving space for the // The fact that we're a list should keep the control from reserving space for the
// expander buttons... but it doesn't. Fix by forcing the indent to 0. // expander buttons... but it doesn't. Fix by forcing the indent to 0.
@ -155,6 +150,10 @@ DIALOG_SELECT_NET_FROM_LIST::DIALOG_SELECT_NET_FROM_LIST(
adjustListColumns(); adjustListColumns();
m_addNet->SetBitmap( KiBitmap( small_plus_xpm ) );
m_renameNet->SetBitmap( KiBitmap( small_edit_xpm ) );
m_deleteNet->SetBitmap( KiBitmap( trash_xpm ) );
m_sdbSizerOK->SetDefault(); m_sdbSizerOK->SetDefault();
FinishDialogSettings(); FinishDialogSettings();
@ -277,7 +276,7 @@ std::vector<CN_ITEM*> DIALOG_SELECT_NET_FROM_LIST::relevantConnectivityItems() c
std::vector<CN_ITEM*> cn_items; std::vector<CN_ITEM*> cn_items;
cn_items.reserve( 1024 ); cn_items.reserve( 1024 );
for( auto& cn_item : m_brd->GetConnectivity()->GetConnectivityAlgo()->ItemList() ) for( CN_ITEM* cn_item : m_brd->GetConnectivity()->GetConnectivityAlgo()->ItemList() )
{ {
if( cn_item->Valid() && type_bits[cn_item->Parent()->Type()] ) if( cn_item->Valid() && type_bits[cn_item->Parent()->Type()] )
cn_items.push_back( cn_item ); cn_items.push_back( cn_item );
@ -323,8 +322,8 @@ void DIALOG_SELECT_NET_FROM_LIST::deleteRow( const ROW_DESC& aRow )
} }
void DIALOG_SELECT_NET_FROM_LIST::setValue( void DIALOG_SELECT_NET_FROM_LIST::setValue( const ROW_DESC& aRow, const COLUMN_ID& aCol,
const ROW_DESC& aRow, const COLUMN_ID& aCol, wxString aVal ) wxString aVal )
{ {
if( aRow ) if( aRow )
m_netsList->SetValue( aVal, aRow.row_num, aCol.col_num ); m_netsList->SetValue( aVal, aRow.row_num, aCol.col_num );
@ -369,7 +368,7 @@ void DIALOG_SELECT_NET_FROM_LIST::OnBoardItemAdded( BOARD& aBoard, BOARD_ITEM* a
std::sort( m_list_items_by_net.begin(), m_list_items_by_net.end(), std::sort( m_list_items_by_net.begin(), m_list_items_by_net.end(),
LIST_ITEM_NET_CMP_LESS( m_list_items ) ); LIST_ITEM_NET_CMP_LESS( m_list_items ) );
auto& new_i = m_list_items.back(); LIST_ITEM& new_i = m_list_items.back();
new_i.m_pad_count = m_brd->GetNodesCount( net->GetNet() ); new_i.m_pad_count = m_brd->GetNodesCount( net->GetNet() );
wxVector<wxVariant> new_row( 7 ); wxVector<wxVariant> new_row( 7 );
@ -386,14 +385,14 @@ void DIALOG_SELECT_NET_FROM_LIST::OnBoardItemAdded( BOARD& aBoard, BOARD_ITEM* a
return; return;
} }
else if( auto* i = dynamic_cast<BOARD_CONNECTED_ITEM*>( aBoardItem ) ) else if( BOARD_CONNECTED_ITEM* i = dynamic_cast<BOARD_CONNECTED_ITEM*>( aBoardItem ) )
{ {
auto r = findRow( i->GetNet() ); const ROW_DESC& r = findRow( i->GetNet() );
if( r ) if( r )
{ {
// try to handle frequent operations quickly. // try to handle frequent operations quickly.
if( auto* track = dynamic_cast<TRACK*>( i ) ) if( TRACK* track = dynamic_cast<TRACK*>( i ) )
{ {
int len = track->GetLength(); int len = track->GetLength();
r.by_row->m_board_wire_length += len; r.by_row->m_board_wire_length += len;
@ -420,16 +419,16 @@ void DIALOG_SELECT_NET_FROM_LIST::OnBoardItemAdded( BOARD& aBoard, BOARD_ITEM* a
void DIALOG_SELECT_NET_FROM_LIST::OnBoardItemRemoved( BOARD& aBoard, BOARD_ITEM* aBoardItem ) void DIALOG_SELECT_NET_FROM_LIST::OnBoardItemRemoved( BOARD& aBoard, BOARD_ITEM* aBoardItem )
{ {
if( auto* net = dynamic_cast<NETINFO_ITEM*>( aBoardItem ) ) if( NETINFO_ITEM* net = dynamic_cast<NETINFO_ITEM*>( aBoardItem ) )
{ {
deleteRow( findRow( net ) ); deleteRow( findRow( net ) );
return; return;
} }
else if( auto* mod = dynamic_cast<MODULE*>( aBoardItem ) ) else if( MODULE* mod = dynamic_cast<MODULE*>( aBoardItem ) )
{ {
for( const D_PAD* pad : mod->Pads() ) for( const D_PAD* pad : mod->Pads() )
{ {
auto r = findRow( pad->GetNet() ); const ROW_DESC& r = findRow( pad->GetNet() );
if( r ) if( r )
{ {
@ -442,14 +441,14 @@ void DIALOG_SELECT_NET_FROM_LIST::OnBoardItemRemoved( BOARD& aBoard, BOARD_ITEM*
} }
} }
} }
else if( auto* i = dynamic_cast<BOARD_CONNECTED_ITEM*>( aBoardItem ) ) else if( BOARD_CONNECTED_ITEM* i = dynamic_cast<BOARD_CONNECTED_ITEM*>( aBoardItem ) )
{ {
auto r = findRow( i->GetNet() ); const ROW_DESC& r = findRow( i->GetNet() );
if( r ) if( r )
{ {
// try to handle frequent operations quickly. // try to handle frequent operations quickly.
if( auto* track = dynamic_cast<TRACK*>( i ) ) if( TRACK* track = dynamic_cast<TRACK*>( i ) )
{ {
int len = track->GetLength(); int len = track->GetLength();
r.by_row->m_board_wire_length -= len; r.by_row->m_board_wire_length -= len;
@ -520,22 +519,22 @@ void DIALOG_SELECT_NET_FROM_LIST::updateNet( NETINFO_ITEM* aNet )
return; return;
} }
auto all_cn_items = relevantConnectivityItems(); std::vector<CN_ITEM*> all_cn_items = relevantConnectivityItems();
LIST_ITEM list_item( aNet ); LIST_ITEM list_item( aNet );
list_item.m_pad_count = node_count; list_item.m_pad_count = node_count;
const auto cn_items = std::equal_range( const auto cn_items = std::equal_range( all_cn_items.begin(), all_cn_items.end(),
all_cn_items.begin(), all_cn_items.end(), aNet->GetNet(), NETCODE_CMP_LESS() ); aNet->GetNet(), NETCODE_CMP_LESS() );
for( auto i = cn_items.first; i != cn_items.second; ++i ) for( auto i = cn_items.first; i != cn_items.second; ++i )
{ {
auto item = ( *i )->Parent(); BOARD_CONNECTED_ITEM* item = ( *i )->Parent();
if( item->Type() == PCB_PAD_T ) if( item->Type() == PCB_PAD_T )
list_item.m_chip_wire_length += static_cast<D_PAD*>( item )->GetPadToDieLength(); list_item.m_chip_wire_length += static_cast<D_PAD*>( item )->GetPadToDieLength();
else if( auto* track = dynamic_cast<TRACK*>( item ) ) else if( TRACK* track = dynamic_cast<TRACK*>( item ) )
{ {
list_item.m_board_wire_length += track->GetLength(); list_item.m_board_wire_length += track->GetLength();
@ -589,7 +588,6 @@ void DIALOG_SELECT_NET_FROM_LIST::buildNetsList()
std::vector<CN_ITEM*> prefiltered_cn_items = relevantConnectivityItems(); std::vector<CN_ITEM*> prefiltered_cn_items = relevantConnectivityItems();
// collect all nets which pass the filter string. // collect all nets which pass the filter string.
struct NET_INFO struct NET_INFO
@ -618,7 +616,7 @@ void DIALOG_SELECT_NET_FROM_LIST::buildNetsList()
std::vector<NET_INFO> nets; std::vector<NET_INFO> nets;
nets.reserve( m_brd->GetNetInfo().NetsByNetcode().size() ); nets.reserve( m_brd->GetNetInfo().NetsByNetcode().size() );
for( auto&& ni : m_brd->GetNetInfo().NetsByNetcode() ) for( const std::pair<const int, NETINFO_ITEM*>& ni : m_brd->GetNetInfo().NetsByNetcode() )
{ {
if( netFilterMatches( ni.second ) ) if( netFilterMatches( ni.second ) )
nets.emplace_back( NET_INFO{ ni.first, ni.second, 0 } ); nets.emplace_back( NET_INFO{ ni.first, ni.second, 0 } );
@ -627,37 +625,37 @@ void DIALOG_SELECT_NET_FROM_LIST::buildNetsList()
// count the pads for each net. since the nets are sorted by netcode // count the pads for each net. since the nets are sorted by netcode
// this way around is faster than using counting pads for each net. // this way around is faster than using counting pads for each net.
for( auto&& mod : m_brd->Modules() ) for( MODULE* mod : m_brd->Modules() )
{ {
for( auto&& pad : mod->Pads() ) for( D_PAD* pad : mod->Pads() )
{ {
auto i = std::lower_bound( auto i = std::lower_bound( nets.begin(), nets.end(), pad->GetNetCode(),
nets.begin(), nets.end(), pad->GetNetCode(), NET_INFO_CMP_LESS() ); NET_INFO_CMP_LESS() );
if( i != nets.end() && i->netcode == pad->GetNetCode() ) if( i != nets.end() && i->netcode == pad->GetNetCode() )
i->pad_count += 1; i->pad_count += 1;
} }
} }
for( auto&& ni : nets ) for( NET_INFO& ni : nets )
{ {
if( !m_cbShowZeroPad->IsChecked() && ni.pad_count == 0 ) if( !m_cbShowZeroPad->IsChecked() && ni.pad_count == 0 )
continue; continue;
m_list_items.emplace_back( ni.net ); m_list_items.emplace_back( ni.net );
auto& list_item = m_list_items.back(); LIST_ITEM& list_item = m_list_items.back();
const auto cn_items = std::equal_range( prefiltered_cn_items.begin(), const auto cn_items = std::equal_range( prefiltered_cn_items.begin(),
prefiltered_cn_items.end(), ni.netcode, NETCODE_CMP_LESS() ); prefiltered_cn_items.end(), ni.netcode, NETCODE_CMP_LESS() );
for( auto i = cn_items.first; i != cn_items.second; ++i ) for( auto i = cn_items.first; i != cn_items.second; ++i )
{ {
auto item = ( *i )->Parent(); BOARD_CONNECTED_ITEM* item = ( *i )->Parent();
if( item->Type() == PCB_PAD_T ) if( item->Type() == PCB_PAD_T )
list_item.m_chip_wire_length += static_cast<D_PAD*>( item )->GetPadToDieLength(); list_item.m_chip_wire_length += static_cast<D_PAD*>( item )->GetPadToDieLength();
else if( auto* track = dynamic_cast<TRACK*>( item ) ) else if( TRACK* track = dynamic_cast<TRACK*>( item ) )
{ {
list_item.m_board_wire_length += track->GetLength(); list_item.m_board_wire_length += track->GetLength();
@ -673,7 +671,7 @@ void DIALOG_SELECT_NET_FROM_LIST::buildNetsList()
wxVector<wxVariant> dataLine; wxVector<wxVariant> dataLine;
dataLine.resize( 7 ); dataLine.resize( 7 );
for( auto& i : m_list_items ) for( LIST_ITEM& i : m_list_items )
{ {
dataLine[COLUMN_NET] = formatNetCode( i.m_net ); dataLine[COLUMN_NET] = formatNetCode( i.m_net );
dataLine[COLUMN_NAME] = formatNetName( i.m_net ); dataLine[COLUMN_NAME] = formatNetName( i.m_net );
@ -699,14 +697,14 @@ void DIALOG_SELECT_NET_FROM_LIST::buildNetsList()
m_wasSelected = false; m_wasSelected = false;
else else
{ {
auto r = findRow( prev_selected_netcode ); const ROW_DESC& r = findRow( prev_selected_netcode );
if( r ) if( r )
{ {
m_selection = r.by_row->m_net->GetNetname(); m_selection = r.by_row->m_net->GetNetname();
m_wasSelected = true; m_wasSelected = true;
auto i = m_netsList->RowToItem( r.row_num ); wxDataViewItem i = m_netsList->RowToItem( r.row_num );
m_netsList->Select( i ); m_netsList->Select( i );
m_netsList->EnsureVisible( i ); m_netsList->EnsureVisible( i );
} }
@ -716,11 +714,11 @@ void DIALOG_SELECT_NET_FROM_LIST::buildNetsList()
void DIALOG_SELECT_NET_FROM_LIST::HighlightNet( NETINFO_ITEM* aNet ) void DIALOG_SELECT_NET_FROM_LIST::HighlightNet( NETINFO_ITEM* aNet )
{ {
const auto r = findRow( aNet ); const ROW_DESC& r = findRow( aNet );
if( r ) if( r )
{ {
auto i = m_netsList->RowToItem( r.row_num ); wxDataViewItem i = m_netsList->RowToItem( r.row_num );
m_netsList->Select( i ); m_netsList->Select( i );
m_netsList->EnsureVisible( i ); m_netsList->EnsureVisible( i );
} }
@ -754,7 +752,7 @@ void DIALOG_SELECT_NET_FROM_LIST::onSelChanged( wxDataViewEvent& )
if( selected_row >= 0 && selected_row < static_cast<int>( m_list_items.size() ) ) if( selected_row >= 0 && selected_row < static_cast<int>( m_list_items.size() ) )
{ {
auto* net = m_list_items[selected_row].m_net; NETINFO_ITEM* net = m_list_items[selected_row].m_net;
m_selection = net->GetNetname(); m_selection = net->GetNetname();
m_wasSelected = true; m_wasSelected = true;
@ -772,10 +770,9 @@ void DIALOG_SELECT_NET_FROM_LIST::adjustListColumns()
int w0, w1, w2, w3, w4, w5, w6; int w0, w1, w2, w3, w4, w5, w6;
/** /**
* Calculating optimal width of the first (Net) and * Calculating optimal width of the first (Net) and the last (Pad Count) columns.
* the last (Pad Count) columns. That width must be * That width must be enough to fit column header label and be not less than width of
* enough to fit column header label and be not less * four chars (0000).
* than width of four chars (0000).
*/ */
wxClientDC dc( GetParent() ); wxClientDC dc( GetParent() );
@ -792,26 +789,19 @@ void DIALOG_SELECT_NET_FROM_LIST::adjustListColumns()
// Considering left and right margins. // Considering left and right margins.
// For wxRenderGeneric it is 5px. // For wxRenderGeneric it is 5px.
w0 = std::max( w0+10, minw_col0); m_netsList->GetColumn( 0 )->SetWidth( std::max( w0 + 10, minw_col0 ) );
w2 = std::max( w2+10, minw); m_netsList->GetColumn( 2 )->SetWidth( w2 + 10 );
w3 = std::max( w3+10, minw); m_netsList->GetColumn( 3 )->SetWidth( w3 + 10 );
w4 = std::max( w4+10, minw); m_netsList->GetColumn( 4 )->SetWidth( std::max( w4 + 10, minw ) );
w5 = std::max( w5+10, minw); m_netsList->GetColumn( 5 )->SetWidth( std::max( w5 + 10, minw ) );
w6 = std::max( w6+10, minw); m_netsList->GetColumn( 6 )->SetWidth( std::max( w6 + 10, minw ) );
m_netsList->GetColumn( 0 )->SetWidth( w0 );
m_netsList->GetColumn( 2 )->SetWidth( w2 );
m_netsList->GetColumn( 3 )->SetWidth( w3 );
m_netsList->GetColumn( 4 )->SetWidth( w4 );
m_netsList->GetColumn( 5 )->SetWidth( w5 );
m_netsList->GetColumn( 6 )->SetWidth( w6 );
// At resizing of the list the width of middle column (Net Names) changes only. // At resizing of the list the width of middle column (Net Names) changes only.
int width = m_netsList->GetClientSize().x; int width = m_netsList->GetClientSize().x;
w1 = width - w0 - w2 - w3 - w4 - w5 - w6; w1 = width - w0 - w2 - w3 - w4 - w5 - w6;
// Column 1 (net names) need a minimal width to display net names // Column 1 (net names) need a minimal width to display net names
dc.GetTextExtent( "MMMMMMMMMMMMMMMMMMMM", &minw, &h ); dc.GetTextExtent( "MMMMMMMMMMMMMMMMMM", &minw, &h );
w1 = std::max( w1, minw ); w1 = std::max( w1, minw );
m_netsList->GetColumn( 1 )->SetWidth( w1 ); m_netsList->GetColumn( 1 )->SetWidth( w1 );
@ -834,6 +824,129 @@ bool DIALOG_SELECT_NET_FROM_LIST::GetNetName( wxString& aName ) const
} }
void DIALOG_SELECT_NET_FROM_LIST::onAddNet( wxCommandEvent& aEvent )
{
wxString newNetName;
NETNAME_VALIDATOR validator( &newNetName );
WX_TEXT_ENTRY_DIALOG dlg( this, _( "Net name:" ), _( "New Net" ), newNetName );
dlg.SetTextValidator( validator );
while( true )
{
if( dlg.ShowModal() != wxID_OK || dlg.GetValue().IsEmpty() )
return; //Aborted by user
newNetName = dlg.GetValue();
if( m_brd->FindNet( newNetName ) )
{
DisplayError( this, wxString::Format( _( "Net name '%s' is already in use." ),
newNetName ) );
newNetName = wxEmptyString;
}
else
{
break;
}
}
NETINFO_ITEM *newnet = new NETINFO_ITEM( m_brd, dlg.GetValue(), 0 );
m_brd->Add( newnet );
m_frame->OnModify();
// We'll get an OnBoardItemChanged callback from this to update our listbox
}
void DIALOG_SELECT_NET_FROM_LIST::onRenameNet( wxCommandEvent& aEvent )
{
int selected_row = m_netsList->GetSelectedRow();
if( selected_row >= 0 && selected_row < static_cast<int>( m_list_items.size() ) )
{
NETINFO_ITEM* net = m_list_items[selected_row].m_net;
wxString fullNetName = net->GetNetname();
wxString netPath;
wxString shortNetName;
if( fullNetName.Contains( "/" ) )
{
netPath = fullNetName.BeforeLast( '/' ) + '/';
shortNetName = fullNetName.AfterLast( '/' );
}
else
{
shortNetName = fullNetName;
}
wxString unescapedShortName = UnescapeString( shortNetName );
WX_TEXT_ENTRY_DIALOG dlg( this, _( "Net name:" ), _( "Rename Net" ), unescapedShortName );
NETNAME_VALIDATOR validator( &unescapedShortName );
dlg.SetTextValidator( validator );
while( true )
{
if( dlg.ShowModal() != wxID_OK )
return; //Aborted by user
unescapedShortName = dlg.GetValue();
if( unescapedShortName.IsEmpty() )
{
DisplayError( this, wxString::Format( _( "Net name cannot be empty." ),
unescapedShortName ) );
continue;
}
shortNetName = EscapeString( unescapedShortName, CTX_NETNAME );
fullNetName = netPath + shortNetName;
if( m_brd->FindNet( shortNetName ) || m_brd->FindNet( fullNetName ) )
{
DisplayError( this, wxString::Format( _( "Net name '%s' is already in use." ),
unescapedShortName ) );
unescapedShortName = wxEmptyString;
}
else
{
break;
}
}
net->SetNetname( fullNetName );
m_frame->OnModify();
buildNetsList();
m_netsList->Refresh();
}
}
void DIALOG_SELECT_NET_FROM_LIST::onDeleteNet( wxCommandEvent& aEvent )
{
int selected_row = m_netsList->GetSelectedRow();
if( selected_row >= 0 && selected_row < static_cast<int>( m_list_items.size() ) )
{
NETINFO_ITEM* net = m_list_items[selected_row].m_net;
if( m_list_items[selected_row].m_pad_count > 0 )
{
if( !IsOK( this, _( "Net is in use. Delete anyway?" ) ) )
return;
}
m_brd->Remove( net );
m_frame->OnModify();
// We'll get an OnBoardItemChanged callback from this to update our listbox
}
}
void DIALOG_SELECT_NET_FROM_LIST::onReport( wxCommandEvent& aEvent ) void DIALOG_SELECT_NET_FROM_LIST::onReport( wxCommandEvent& aEvent )
{ {
wxFileDialog dlg( this, _( "Report file" ), "", "", wxFileDialog dlg( this, _( "Report file" ), "", "",
@ -860,13 +973,14 @@ void DIALOG_SELECT_NET_FROM_LIST::onReport( wxCommandEvent& aEvent )
// Print list of nets: // Print list of nets:
for( int row = 1; row < rows; row++ ) for( int row = 1; row < rows; row++ )
{ {
txt.Printf( "%s;\"%s\";%s;%s;%s;%s;%s;", m_netsList->GetTextValue( row, COLUMN_NET ), txt.Printf( "%s;\"%s\";%s;%s;%s;%s;%s;",
m_netsList->GetTextValue( row, COLUMN_NAME ), m_netsList->GetTextValue( row, COLUMN_NET ),
m_netsList->GetTextValue( row, COLUMN_PAD_COUNT ), m_netsList->GetTextValue( row, COLUMN_NAME ),
m_netsList->GetTextValue( row, COLUMN_VIA_COUNT ), m_netsList->GetTextValue( row, COLUMN_PAD_COUNT ),
m_netsList->GetTextValue( row, COLUMN_BOARD_LENGTH ), m_netsList->GetTextValue( row, COLUMN_VIA_COUNT ),
m_netsList->GetTextValue( row, COLUMN_CHIP_LENGTH ), m_netsList->GetTextValue( row, COLUMN_BOARD_LENGTH ),
m_netsList->GetTextValue( row, COLUMN_TOTAL_LENGTH ) ); m_netsList->GetTextValue( row, COLUMN_CHIP_LENGTH ),
m_netsList->GetTextValue( row, COLUMN_TOTAL_LENGTH ) );
f.AddLine( txt ); f.AddLine( txt );
} }

View File

@ -94,6 +94,9 @@ private:
void onSelChanged( wxDataViewEvent& event ) override; void onSelChanged( wxDataViewEvent& event ) override;
void onFilterChange( wxCommandEvent& event ) override; void onFilterChange( wxCommandEvent& event ) override;
void onListSize( wxSizeEvent& event ) override; void onListSize( wxSizeEvent& event ) override;
void onAddNet( wxCommandEvent& event ) override;
void onRenameNet( wxCommandEvent& event ) override;
void onDeleteNet( wxCommandEvent& event ) override;
void onReport( wxCommandEvent& event ) override; void onReport( wxCommandEvent& event ) override;
void buildNetsList(); void buildNetsList();

View File

@ -41,14 +41,35 @@ DIALOG_SELECT_NET_FROM_LIST_BASE::DIALOG_SELECT_NET_FROM_LIST_BASE( wxWindow* pa
bSizerMain->Add( m_netsList, 1, wxEXPAND|wxRIGHT|wxLEFT, 10 ); bSizerMain->Add( m_netsList, 1, wxEXPAND|wxRIGHT|wxLEFT, 10 );
wxBoxSizer* bSizerBottom; wxBoxSizer* bSizerListButtons;
bSizerBottom = new wxBoxSizer( wxHORIZONTAL ); bSizerListButtons = new wxBoxSizer( wxHORIZONTAL );
m_addNet = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
bSizerListButtons->Add( m_addNet, 0, wxTOP|wxBOTTOM|wxLEFT, 5 );
m_renameNet = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
bSizerListButtons->Add( m_renameNet, 0, wxALL, 5 );
bSizerListButtons->Add( 15, 0, 0, wxEXPAND, 5 );
m_deleteNet = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
bSizerListButtons->Add( m_deleteNet, 0, wxALL, 5 );
bSizerListButtons->Add( 0, 0, 1, wxEXPAND, 5 );
m_ReportButt = new wxButton( this, wxID_ANY, _("Create Report..."), wxDefaultPosition, wxDefaultSize, 0 ); m_ReportButt = new wxButton( this, wxID_ANY, _("Create Report..."), wxDefaultPosition, wxDefaultSize, 0 );
bSizerBottom->Add( m_ReportButt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); bSizerListButtons->Add( m_ReportButt, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
bSizerBottom->Add( 0, 0, 1, wxEXPAND, 5 ); bSizerMain->Add( bSizerListButtons, 0, wxEXPAND|wxALL, 5 );
m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
bSizerMain->Add( m_staticline1, 0, wxEXPAND | wxALL, 5 );
wxBoxSizer* bSizerBottom;
bSizerBottom = new wxBoxSizer( wxHORIZONTAL );
m_sdbSizer = new wxStdDialogButtonSizer(); m_sdbSizer = new wxStdDialogButtonSizer();
m_sdbSizerOK = new wxButton( this, wxID_OK ); m_sdbSizerOK = new wxButton( this, wxID_OK );
@ -57,7 +78,7 @@ DIALOG_SELECT_NET_FROM_LIST_BASE::DIALOG_SELECT_NET_FROM_LIST_BASE( wxWindow* pa
m_sdbSizer->AddButton( m_sdbSizerCancel ); m_sdbSizer->AddButton( m_sdbSizerCancel );
m_sdbSizer->Realize(); m_sdbSizer->Realize();
bSizerBottom->Add( m_sdbSizer, 0, wxALL|wxEXPAND, 5 ); bSizerBottom->Add( m_sdbSizer, 1, wxALL|wxEXPAND, 5 );
bSizerMain->Add( bSizerBottom, 0, wxEXPAND|wxLEFT, 5 ); bSizerMain->Add( bSizerBottom, 0, wxEXPAND|wxLEFT, 5 );
@ -65,6 +86,7 @@ DIALOG_SELECT_NET_FROM_LIST_BASE::DIALOG_SELECT_NET_FROM_LIST_BASE( wxWindow* pa
this->SetSizer( bSizerMain ); this->SetSizer( bSizerMain );
this->Layout(); this->Layout();
bSizerMain->Fit( this );
this->Centre( wxBOTH ); this->Centre( wxBOTH );
@ -73,6 +95,9 @@ DIALOG_SELECT_NET_FROM_LIST_BASE::DIALOG_SELECT_NET_FROM_LIST_BASE( wxWindow* pa
m_cbShowZeroPad->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SELECT_NET_FROM_LIST_BASE::onFilterChange ), NULL, this ); m_cbShowZeroPad->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SELECT_NET_FROM_LIST_BASE::onFilterChange ), NULL, this );
m_netsList->Connect( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( DIALOG_SELECT_NET_FROM_LIST_BASE::onSelChanged ), NULL, this ); m_netsList->Connect( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( DIALOG_SELECT_NET_FROM_LIST_BASE::onSelChanged ), NULL, this );
m_netsList->Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_SELECT_NET_FROM_LIST_BASE::onListSize ), NULL, this ); m_netsList->Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_SELECT_NET_FROM_LIST_BASE::onListSize ), NULL, this );
m_addNet->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SELECT_NET_FROM_LIST_BASE::onAddNet ), NULL, this );
m_renameNet->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SELECT_NET_FROM_LIST_BASE::onRenameNet ), NULL, this );
m_deleteNet->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SELECT_NET_FROM_LIST_BASE::onDeleteNet ), NULL, this );
m_ReportButt->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SELECT_NET_FROM_LIST_BASE::onReport ), NULL, this ); m_ReportButt->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SELECT_NET_FROM_LIST_BASE::onReport ), NULL, this );
} }
@ -83,6 +108,9 @@ DIALOG_SELECT_NET_FROM_LIST_BASE::~DIALOG_SELECT_NET_FROM_LIST_BASE()
m_cbShowZeroPad->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SELECT_NET_FROM_LIST_BASE::onFilterChange ), NULL, this ); m_cbShowZeroPad->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_SELECT_NET_FROM_LIST_BASE::onFilterChange ), NULL, this );
m_netsList->Disconnect( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( DIALOG_SELECT_NET_FROM_LIST_BASE::onSelChanged ), NULL, this ); m_netsList->Disconnect( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( DIALOG_SELECT_NET_FROM_LIST_BASE::onSelChanged ), NULL, this );
m_netsList->Disconnect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_SELECT_NET_FROM_LIST_BASE::onListSize ), NULL, this ); m_netsList->Disconnect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_SELECT_NET_FROM_LIST_BASE::onListSize ), NULL, this );
m_addNet->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SELECT_NET_FROM_LIST_BASE::onAddNet ), NULL, this );
m_renameNet->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SELECT_NET_FROM_LIST_BASE::onRenameNet ), NULL, this );
m_deleteNet->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SELECT_NET_FROM_LIST_BASE::onDeleteNet ), NULL, this );
m_ReportButt->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SELECT_NET_FROM_LIST_BASE::onReport ), NULL, this ); m_ReportButt->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SELECT_NET_FROM_LIST_BASE::onReport ), NULL, this );
} }

View File

@ -45,7 +45,7 @@
<property name="minimum_size">-1,-1</property> <property name="minimum_size">-1,-1</property>
<property name="name">DIALOG_SELECT_NET_FROM_LIST_BASE</property> <property name="name">DIALOG_SELECT_NET_FROM_LIST_BASE</property>
<property name="pos"></property> <property name="pos"></property>
<property name="size">720,397</property> <property name="size">-1,-1</property>
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property> <property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property> <property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
<property name="title">Net Inspector</property> <property name="title">Net Inspector</property>
@ -301,13 +301,252 @@
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="1">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxEXPAND|wxLEFT</property> <property name="flag">wxEXPAND|wxALL</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxBoxSizer" expanded="1"> <object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property> <property name="minimum_size"></property>
<property name="name">bSizerBottom</property> <property name="name">bSizerListButtons</property>
<property name="orient">wxHORIZONTAL</property> <property name="orient">wxHORIZONTAL</property>
<property name="permission">none</property> <property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxTOP|wxBOTTOM|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxBitmapButton" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="bitmap"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="current"></property>
<property name="default">0</property>
<property name="default_pane">0</property>
<property name="disabled"></property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="focus"></property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Add Net</property>
<property name="margins"></property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_addNet</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="position"></property>
<property name="pressed"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnButtonClick">onAddNet</event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxBitmapButton" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="bitmap"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="current"></property>
<property name="default">0</property>
<property name="default_pane">0</property>
<property name="disabled"></property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="focus"></property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Rename Net</property>
<property name="margins"></property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_renameNet</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="position"></property>
<property name="pressed"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnButtonClick">onRenameNet</event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">0</property>
<object class="spacer" expanded="1">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">15</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxBitmapButton" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="bitmap"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="current"></property>
<property name="default">0</property>
<property name="default_pane">0</property>
<property name="disabled"></property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="focus"></property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Delete Net</property>
<property name="margins"></property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_deleteNet</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="position"></property>
<property name="pressed"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnButtonClick">onDeleteNet</event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="spacer" expanded="1">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="1">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxALL|wxALIGN_CENTER_VERTICAL</property> <property name="flag">wxALL|wxALIGN_CENTER_VERTICAL</property>
@ -381,20 +620,79 @@
<event name="OnButtonClick">onReport</event> <event name="OnButtonClick">onReport</event>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> </object>
<property name="border">5</property> </object>
<property name="flag">wxEXPAND</property> <object class="sizeritem" expanded="1">
<property name="proportion">1</property> <property name="border">5</property>
<object class="spacer" expanded="1"> <property name="flag">wxEXPAND | wxALL</property>
<property name="height">0</property> <property name="proportion">0</property>
<property name="permission">protected</property> <object class="wxStaticLine" expanded="1">
<property name="width">0</property> <property name="BottomDockable">1</property>
</object> <property name="LeftDockable">1</property>
</object> <property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_staticline1</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxLI_HORIZONTAL</property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxLEFT</property>
<property name="proportion">0</property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bSizerBottom</property>
<property name="orient">wxHORIZONTAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="0"> <object class="sizeritem" expanded="0">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxALL|wxEXPAND</property> <property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">0</property> <property name="proportion">1</property>
<object class="wxStdDialogButtonSizer" expanded="0"> <object class="wxStdDialogButtonSizer" expanded="0">
<property name="Apply">0</property> <property name="Apply">0</property>
<property name="Cancel">1</property> <property name="Cancel">1</property>

View File

@ -21,10 +21,12 @@
#include <wx/checkbox.h> #include <wx/checkbox.h>
#include <wx/sizer.h> #include <wx/sizer.h>
#include <wx/dataview.h> #include <wx/dataview.h>
#include <wx/bmpbuttn.h>
#include <wx/bitmap.h> #include <wx/bitmap.h>
#include <wx/image.h> #include <wx/image.h>
#include <wx/icon.h> #include <wx/icon.h>
#include <wx/button.h> #include <wx/button.h>
#include <wx/statline.h>
#include <wx/dialog.h> #include <wx/dialog.h>
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
@ -42,7 +44,11 @@ class DIALOG_SELECT_NET_FROM_LIST_BASE : public DIALOG_SHIM
wxTextCtrl* m_textCtrlFilter; wxTextCtrl* m_textCtrlFilter;
wxCheckBox* m_cbShowZeroPad; wxCheckBox* m_cbShowZeroPad;
wxDataViewListCtrl* m_netsList; wxDataViewListCtrl* m_netsList;
wxBitmapButton* m_addNet;
wxBitmapButton* m_renameNet;
wxBitmapButton* m_deleteNet;
wxButton* m_ReportButt; wxButton* m_ReportButt;
wxStaticLine* m_staticline1;
wxStdDialogButtonSizer* m_sdbSizer; wxStdDialogButtonSizer* m_sdbSizer;
wxButton* m_sdbSizerOK; wxButton* m_sdbSizerOK;
wxButton* m_sdbSizerCancel; wxButton* m_sdbSizerCancel;
@ -51,12 +57,15 @@ class DIALOG_SELECT_NET_FROM_LIST_BASE : public DIALOG_SHIM
virtual void onFilterChange( wxCommandEvent& event ) { event.Skip(); } virtual void onFilterChange( wxCommandEvent& event ) { event.Skip(); }
virtual void onSelChanged( wxDataViewEvent& event ) { event.Skip(); } virtual void onSelChanged( wxDataViewEvent& event ) { event.Skip(); }
virtual void onListSize( wxSizeEvent& event ) { event.Skip(); } virtual void onListSize( wxSizeEvent& event ) { event.Skip(); }
virtual void onAddNet( wxCommandEvent& event ) { event.Skip(); }
virtual void onRenameNet( wxCommandEvent& event ) { event.Skip(); }
virtual void onDeleteNet( wxCommandEvent& event ) { event.Skip(); }
virtual void onReport( wxCommandEvent& event ) { event.Skip(); } virtual void onReport( wxCommandEvent& event ) { event.Skip(); }
public: public:
DIALOG_SELECT_NET_FROM_LIST_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Net Inspector"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 720,397 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); DIALOG_SELECT_NET_FROM_LIST_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Net Inspector"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~DIALOG_SELECT_NET_FROM_LIST_BASE(); ~DIALOG_SELECT_NET_FROM_LIST_BASE();
}; };

View File

@ -236,6 +236,21 @@ public:
*/ */
const wxString& GetShortNetname() const { return m_ShortNetname; } const wxString& GetShortNetname() const { return m_ShortNetname; }
/**
* Function SetNetname
* Sets the long netname to \a aNetName, and the short netname to the last token in
* the long netname's path.
*/
void SetNetname( const wxString& aNewName )
{
m_Netname = aNewName;
if( aNewName.Contains( "/" ) )
m_ShortNetname = aNewName.AfterLast( '/' );
else
m_ShortNetname = aNewName;
}
bool IsCurrent() const { return m_isCurrent; } bool IsCurrent() const { return m_isCurrent; }
void SetIsCurrent( bool isCurrent ) { m_isCurrent = isCurrent; } void SetIsCurrent( bool isCurrent ) { m_isCurrent = isCurrent; }

View File

@ -864,6 +864,5 @@ bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist )
return false; return false;
} }
m_reporter->ReportTail( _( "Netlist update successful!" ), RPT_SEVERITY_ACTION );
return true; return true;
} }

View File

@ -1,12 +1,9 @@
/**
* @file pcb_netlist.cpp
*/
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 1992-2011 Jean-Pierre Charras. * Copyright (C) 1992-2011 Jean-Pierre Charras.
* Copyright (C) 2013 Wayne Stambaugh <stambaughw@verizon.net>. * Copyright (C) 2013 Wayne Stambaugh <stambaughw@verizon.net>.
* Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -27,13 +24,9 @@
*/ */
#include <macros.h>
#include <refdes_utils.h> #include <refdes_utils.h>
#include <reporter.h>
#include "pcb_netlist.h" #include "pcb_netlist.h"
#include <class_module.h> #include <class_module.h>
#include <eda_pattern_match.h>
int COMPONENT_NET::Format( OUTPUTFORMATTER* aOut, int aNestLevel, int aCtl ) int COMPONENT_NET::Format( OUTPUTFORMATTER* aOut, int aNestLevel, int aCtl )
@ -220,14 +213,3 @@ bool NETLIST::AnyFootprintsLinked() const
} }
bool NETLIST::AllFootprintsLinked() const
{
for( unsigned i = 0; i < m_components.size(); i++ )
{
if( m_components[i].GetFPID().empty() )
return false;
}
return true;
}

View File

@ -97,7 +97,6 @@ class COMPONENT
/// The #LIB_ID of the footprint assigned to the component. /// The #LIB_ID of the footprint assigned to the component.
LIB_ID m_fpid; LIB_ID m_fpid;
/// The alt LIB_ID of the footprint, when there are 2 different assigned footprints, /// The alt LIB_ID of the footprint, when there are 2 different assigned footprints,
/// One from the netlist, the other from the .cmp file. /// One from the netlist, the other from the .cmp file.
/// this one is a copy of the netlist footprint assignment /// this one is a copy of the netlist footprint assignment
@ -106,15 +105,12 @@ class COMPONENT
/// The #MODULE loaded for #m_fpid. /// The #MODULE loaded for #m_fpid.
std::unique_ptr< MODULE > m_footprint; std::unique_ptr< MODULE > m_footprint;
/// Set to true if #m_fpid was changed when the footprint link file was read.
bool m_footprintChanged;
static COMPONENT_NET m_emptyNet; static COMPONENT_NET m_emptyNet;
public: public:
COMPONENT( const LIB_ID& aFPID, COMPONENT( const LIB_ID& aFPID,
const wxString& aReference, const wxString& aReference,
const wxString& aValue, const wxString& aValue,
const KIID_PATH& aPath ) const KIID_PATH& aPath )
{ {
m_fpid = aFPID; m_fpid = aFPID;
@ -122,7 +118,6 @@ public:
m_value = aValue; m_value = aValue;
m_pinCount = 0; m_pinCount = 0;
m_path = aPath; m_path = aPath;
m_footprintChanged = false;
} }
virtual ~COMPONENT() { }; virtual ~COMPONENT() { };
@ -150,35 +145,18 @@ public:
const wxString& GetValue() const { return m_value; } const wxString& GetValue() const { return m_value; }
void SetFPID( const LIB_ID& aFPID ) void SetFPID( const LIB_ID& aFPID ) { m_fpid = aFPID; }
{
m_footprintChanged = !m_fpid.empty() && (m_fpid != aFPID);
m_fpid = aFPID;
}
void SetAltFPID( const LIB_ID& aFPID )
{
m_altFpid = aFPID;
}
const LIB_ID& GetFPID() const { return m_fpid; } const LIB_ID& GetFPID() const { return m_fpid; }
void SetAltFPID( const LIB_ID& aFPID ) { m_altFpid = aFPID; }
const LIB_ID& GetAltFPID() const { return m_altFpid; } const LIB_ID& GetAltFPID() const { return m_altFpid; }
const KIID_PATH& GetPath() const { return m_path; } const KIID_PATH& GetPath() const { return m_path; }
void SetFootprintFilters( const wxArrayString& aFilterList ) void SetFootprintFilters( const wxArrayString& aFilters ) { m_footprintFilters = aFilters; }
{
m_footprintFilters = aFilterList;
}
const wxArrayString& GetFootprintFilters() const { return m_footprintFilters; } const wxArrayString& GetFootprintFilters() const { return m_footprintFilters; }
void SetPinCount( int aPinCount ) void SetPinCount( int aPinCount ) { m_pinCount = aPinCount; }
{
m_pinCount = aPinCount;
}
int GetPinCount() const { return m_pinCount; } int GetPinCount() const { return m_pinCount; }
MODULE* GetModule( bool aRelease = false ) MODULE* GetModule( bool aRelease = false )
@ -193,15 +171,11 @@ public:
return aLibrary == m_library && aName == m_name; return aLibrary == m_library && aName == m_name;
} }
bool FootprintChanged() const { return m_footprintChanged; }
void Format( OUTPUTFORMATTER* aOut, int aNestLevel, int aCtl ); void Format( OUTPUTFORMATTER* aOut, int aNestLevel, int aCtl );
}; };
typedef boost::ptr_vector< COMPONENT > COMPONENTS; typedef boost::ptr_vector< COMPONENT > COMPONENTS;
typedef COMPONENTS::iterator COMPONENTS_ITER;
typedef COMPONENTS::const_iterator COMPONENTS_CITER;
/** /**
@ -300,12 +274,6 @@ public:
m_deleteExtraFootprints = aDeleteExtraFootprints; m_deleteExtraFootprints = aDeleteExtraFootprints;
} }
bool GetDeleteExtraFootprints() const { return m_deleteExtraFootprints; }
void SetIsDryRun( bool aIsDryRun ) { m_isDryRun = aIsDryRun; }
bool IsDryRun() const { return m_isDryRun; }
void SetFindByTimeStamp( bool aFindByTimeStamp ) { m_findByTimeStamp = aFindByTimeStamp; } void SetFindByTimeStamp( bool aFindByTimeStamp ) { m_findByTimeStamp = aFindByTimeStamp; }
bool IsFindByTimeStamp() const { return m_findByTimeStamp; } bool IsFindByTimeStamp() const { return m_findByTimeStamp; }
@ -323,25 +291,6 @@ public:
*/ */
bool AnyFootprintsLinked() const; bool AnyFootprintsLinked() const;
/**
* Function AllFootprintsLinked
* @return true if all components have a footprint link.
*/
bool AllFootprintsLinked() const;
/**
* Function NoFootprintsLinked
* @return true if none of the components have a footprint link.
*/
bool NoFootprintsLinked() const { return !AnyFootprintsLinked(); }
/**
* Function AnyFootprintsChanged
* @return true if any components footprints were changed when the footprint link file
* (*.cmp) was loaded.
*/
bool AnyFootprintsChanged() const;
void Format( const char* aDocName, OUTPUTFORMATTER* aOut, int aNestLevel, int aCtl = 0 ); void Format( const char* aDocName, OUTPUTFORMATTER* aOut, int aNestLevel, int aCtl = 0 );
#define CTL_OMIT_EXTRA (1<<0) #define CTL_OMIT_EXTRA (1<<0)