Symbol editor: improve symbol library save as behavior.
ADDED: Radio button controls to symbol library editor save as file dialog to allow the user to choose the appropriate symbol library table changes to be made after the library is saved. Fixes https://gitlab.com/kicad/code/kicad/issues/4911
This commit is contained in:
parent
157ceedc12
commit
50b171fa33
|
@ -30,6 +30,7 @@
|
|||
#include <core/kicad_algo.h>
|
||||
#include <eeschema_id.h>
|
||||
#include <eeschema_settings.h>
|
||||
#include <env_paths.h>
|
||||
#include <kiface_i.h>
|
||||
#include <kiplatform/app.h>
|
||||
#include <kiway_express.h>
|
||||
|
@ -1307,3 +1308,123 @@ void SYMBOL_EDIT_FRAME::LoadSymbolFromSchematic( const std::unique_ptr<LIB_PART>
|
|||
DisplaySymbolDatasheet();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
bool SYMBOL_EDIT_FRAME::addLibTableEntry( const wxString& aLibFile, TABLE_SCOPE aScope )
|
||||
{
|
||||
wxFileName fn = aLibFile;
|
||||
wxFileName libTableFileName( Prj().GetProjectPath(),
|
||||
SYMBOL_LIB_TABLE::GetSymbolLibTableFileName() );
|
||||
wxString libNickname = fn.GetName();
|
||||
SYMBOL_LIB_TABLE* libTable = Prj().SchSymbolLibTable();
|
||||
const ENV_VAR_MAP& envVars = Pgm().GetLocalEnvVariables();
|
||||
|
||||
if( libTable->HasLibrary( libNickname ) )
|
||||
{
|
||||
wxString tmp;
|
||||
int suffix = 1;
|
||||
|
||||
while( libTable->HasLibrary( libNickname ) )
|
||||
{
|
||||
tmp.Printf( "%s%d", fn.GetName(), suffix );
|
||||
libNickname = tmp;
|
||||
suffix += 1;
|
||||
}
|
||||
}
|
||||
|
||||
SYMBOL_LIB_TABLE_ROW* row = new SYMBOL_LIB_TABLE_ROW();
|
||||
row->SetNickName( libNickname );
|
||||
|
||||
wxString normalizedPath = NormalizePath( aLibFile, &envVars, Prj().GetProjectPath() );
|
||||
|
||||
if( aScope == GLOBAL_LIB_TABLE )
|
||||
{
|
||||
libTable = &SYMBOL_LIB_TABLE::GetGlobalLibTable();
|
||||
libTableFileName = SYMBOL_LIB_TABLE::GetGlobalTableFileName();
|
||||
|
||||
// We cannot normalize against the current project path when saving to global table.
|
||||
normalizedPath = NormalizePath( aLibFile, &envVars, wxEmptyString );
|
||||
}
|
||||
|
||||
if( normalizedPath.IsEmpty() )
|
||||
normalizedPath = aLibFile;
|
||||
|
||||
row->SetFullURI( normalizedPath );
|
||||
|
||||
wxCHECK( libTable->InsertRow( row ), false );
|
||||
|
||||
try
|
||||
{
|
||||
libTable->Save( libTableFileName.GetFullPath() );
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
wxString msg;
|
||||
msg.Printf( _( "Error saving %s symbol library table." ),
|
||||
( aScope == GLOBAL_LIB_TABLE ) ? _( "global" ) : _( "project" ) );
|
||||
|
||||
wxMessageDialog dlg( this, msg, _( "File Save Error" ), wxOK | wxICON_ERROR );
|
||||
dlg.SetExtendedMessage( ioe.What() );
|
||||
dlg.ShowModal();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SYMBOL_EDIT_FRAME::replaceLibTableEntry( const wxString& aLibNickname,
|
||||
const wxString& aLibFile )
|
||||
{
|
||||
// Check the global library table first because checking the project library table
|
||||
// checks the global library table as well due to library chaining.
|
||||
bool isGlobalTable = true;
|
||||
wxFileName libTableFileName = SYMBOL_LIB_TABLE::GetGlobalTableFileName();;
|
||||
const ENV_VAR_MAP& envVars = Pgm().GetLocalEnvVariables();
|
||||
SYMBOL_LIB_TABLE* libTable = &SYMBOL_LIB_TABLE::GetGlobalLibTable();
|
||||
SYMBOL_LIB_TABLE_ROW* row = libTable->FindRow( aLibNickname );
|
||||
|
||||
if( !row )
|
||||
{
|
||||
libTableFileName.SetPath( Prj().GetProjectPath() );
|
||||
libTableFileName.SetName( SYMBOL_LIB_TABLE::GetSymbolLibTableFileName() );
|
||||
libTable = Prj().SchSymbolLibTable();
|
||||
isGlobalTable = false;
|
||||
row = libTable->FindRow( aLibNickname );
|
||||
}
|
||||
|
||||
wxCHECK( row, false );
|
||||
|
||||
wxString projectPath;
|
||||
|
||||
if( !isGlobalTable )
|
||||
projectPath = Prj().GetProjectPath();
|
||||
|
||||
wxString normalizedPath = NormalizePath( aLibFile, &envVars, projectPath );
|
||||
|
||||
if( normalizedPath.IsEmpty() )
|
||||
normalizedPath = aLibFile;
|
||||
|
||||
row->SetFullURI( normalizedPath );
|
||||
row->SetType( "KiCad" );
|
||||
|
||||
try
|
||||
{
|
||||
libTable->Save( libTableFileName.GetFullPath() );
|
||||
}
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
wxString msg;
|
||||
msg.Printf( _( "Error saving %s symbol library table." ),
|
||||
( isGlobalTable ) ? _( "global" ) : _( "project" ) );
|
||||
|
||||
wxMessageDialog dlg( this, msg, _( "File Save Error" ), wxOK | wxICON_ERROR );
|
||||
dlg.SetExtendedMessage( ioe.What() );
|
||||
dlg.ShowModal();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -469,6 +469,35 @@ private:
|
|||
///< Rename LIB_PART aliases to avoid conflicts before adding a symbol to a library.
|
||||
void ensureUniqueName( LIB_PART* aPart, const wxString& aLibrary );
|
||||
|
||||
enum TABLE_SCOPE
|
||||
{
|
||||
GLOBAL_LIB_TABLE,
|
||||
PROJECT_LIB_TABLE
|
||||
};
|
||||
|
||||
/**
|
||||
* Add \a aLibFile to the symbol library table defined by \a aScope.
|
||||
*
|
||||
* @note The library defined by \a aLibFile must be a KiCad (s-expression) library.
|
||||
*
|
||||
* @param aLibFile is the full path and file name of the symbol library to add to the table.
|
||||
* @param aScope defines if \a aLibFile is added to the global or project library table.
|
||||
* @return true if successful or false if a failure occurs.
|
||||
*/
|
||||
bool addLibTableEntry( const wxString& aLibFile, TABLE_SCOPE aScope = GLOBAL_LIB_TABLE );
|
||||
|
||||
/**
|
||||
* Replace the file path of the symbol library table entry \a aLibNickname with \a aLibFile.
|
||||
*
|
||||
* @note The library defined by \a aLibFile must be a KiCad (s-expression) library.
|
||||
*
|
||||
* @param aLibNickmane is the nickname of an existing library table entry.
|
||||
* @param aLibFile is the full path and file name of the symbol library to replace in the
|
||||
* table.
|
||||
* @return true if successful or false if a failure occurs.
|
||||
*/
|
||||
bool replaceLibTableEntry( const wxString& aLibNickname, const wxString& aLibFile );
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
public:
|
||||
|
|
|
@ -45,6 +45,92 @@
|
|||
#include <wx/clipbrd.h>
|
||||
|
||||
|
||||
/**
|
||||
* Helper control to inquire user what to do on library save as operation.
|
||||
*/
|
||||
class SAVE_AS_HELPER : public wxPanel
|
||||
{
|
||||
public:
|
||||
SAVE_AS_HELPER( wxWindow* aParent ) :
|
||||
wxPanel( aParent )
|
||||
{
|
||||
m_simpleSaveAs = new wxRadioButton( this, wxID_ANY, _( "Normal save as operation" ),
|
||||
wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
|
||||
m_simpleSaveAs->SetToolTip( _( "Do not perform any additional operations after saving "
|
||||
"library." ) );
|
||||
m_replaceTableEntry = new wxRadioButton( this, wxID_ANY,
|
||||
_( "Replace library table entry" ) );
|
||||
m_replaceTableEntry->SetToolTip( _( "Replacy symbol library table entry with new library."
|
||||
"\n\nThe original library will no longer be avaliable "
|
||||
"for use." ) );
|
||||
m_addGlobalTableEntry = new wxRadioButton( this, wxID_ANY,
|
||||
_( "Add new global library table entry" ) );
|
||||
m_addGlobalTableEntry->SetToolTip( _( "Add new entry to the global symbol library table."
|
||||
"\n\nThe symbol library table nickname is suffixed "
|
||||
"with\nan integer to ensure no duplicate table "
|
||||
"entries." ) );
|
||||
m_addProjectTableEntry = new wxRadioButton( this, wxID_ANY,
|
||||
_( "Add new project library table entry" ) );
|
||||
m_addProjectTableEntry->SetToolTip( _( "Add new entry to the project symbol library table."
|
||||
"\n\nThe symbol library table nickname is suffixed "
|
||||
"with\nan integer to ensure no duplicate table "
|
||||
"entries." ) );
|
||||
|
||||
wxBoxSizer* sizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
sizer->Add( m_simpleSaveAs, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL, 5 );
|
||||
sizer->Add( m_replaceTableEntry, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5 );
|
||||
sizer->Add( m_addGlobalTableEntry, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5 );
|
||||
sizer->Add( m_addProjectTableEntry, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
SetSizerAndFit( sizer );
|
||||
}
|
||||
|
||||
enum SAH_TYPE
|
||||
{
|
||||
UNDEFINED = -1,
|
||||
NORMAL_SAVE_AS,
|
||||
REPLACE_TABLE_ENTRY,
|
||||
ADD_GLOBAL_TABLE_ENTRY,
|
||||
ADD_PROJECT_TABLE_ENTRY
|
||||
};
|
||||
|
||||
SAH_TYPE GetOption() const
|
||||
{
|
||||
if( m_simpleSaveAs->GetValue() )
|
||||
return SAH_TYPE::NORMAL_SAVE_AS;
|
||||
else if( m_replaceTableEntry->GetValue() )
|
||||
return SAH_TYPE::REPLACE_TABLE_ENTRY;
|
||||
else if( m_addGlobalTableEntry->GetValue() )
|
||||
return ADD_GLOBAL_TABLE_ENTRY;
|
||||
else if( m_addProjectTableEntry->GetValue() )
|
||||
return ADD_PROJECT_TABLE_ENTRY;
|
||||
else
|
||||
return UNDEFINED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new panel to add to a wxFileDialog object.
|
||||
*
|
||||
* The caller owns the created object and is responsible for deleting it.
|
||||
*
|
||||
* @param aParent is the parent window that will own the created object.
|
||||
* @return the newly created panel to add to the wxFileDialog.
|
||||
*/
|
||||
static wxWindow* Create( wxWindow* aParent )
|
||||
{
|
||||
wxCHECK( aParent, nullptr );
|
||||
|
||||
return new SAVE_AS_HELPER( aParent );
|
||||
}
|
||||
|
||||
private:
|
||||
wxRadioButton* m_simpleSaveAs;
|
||||
wxRadioButton* m_replaceTableEntry;
|
||||
wxRadioButton* m_addGlobalTableEntry;
|
||||
wxRadioButton* m_addProjectTableEntry;
|
||||
};
|
||||
|
||||
|
||||
void SYMBOL_EDIT_FRAME::updateTitle()
|
||||
{
|
||||
wxString lib = GetCurLib();
|
||||
|
@ -1026,6 +1112,7 @@ bool SYMBOL_EDIT_FRAME::saveLibrary( const wxString& aLibrary, bool aNewFile )
|
|||
{
|
||||
wxFileName fn;
|
||||
wxString msg;
|
||||
SAVE_AS_HELPER::SAH_TYPE type = SAVE_AS_HELPER::SAH_TYPE::UNDEFINED;
|
||||
SCH_IO_MGR::SCH_FILE_T fileType = SCH_IO_MGR::SCH_FILE_T::SCH_KICAD;
|
||||
PROJECT& prj = Prj();
|
||||
|
||||
|
@ -1056,6 +1143,8 @@ bool SYMBOL_EDIT_FRAME::saveLibrary( const wxString& aLibrary, bool aNewFile )
|
|||
default_path, fn.GetFullName(), wildcards,
|
||||
wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
|
||||
|
||||
dlg.SetExtraControlCreator( &SAVE_AS_HELPER::Create );
|
||||
|
||||
if( dlg.ShowModal() == wxID_CANCEL )
|
||||
return false;
|
||||
|
||||
|
@ -1065,6 +1154,11 @@ bool SYMBOL_EDIT_FRAME::saveLibrary( const wxString& aLibrary, bool aNewFile )
|
|||
|
||||
if( fn.GetExt().IsEmpty() )
|
||||
fn.SetExt( KiCadSymbolLibFileExtension );
|
||||
|
||||
const SAVE_AS_HELPER* sah = dynamic_cast<const SAVE_AS_HELPER*>( dlg.GetExtraControl() );
|
||||
wxCHECK( sah, false );
|
||||
|
||||
type = sah->GetOption();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1091,7 +1185,40 @@ bool SYMBOL_EDIT_FRAME::saveLibrary( const wxString& aLibrary, bool aNewFile )
|
|||
}
|
||||
|
||||
if( !aNewFile )
|
||||
{
|
||||
m_libMgr->ClearLibraryModified( aLibrary );
|
||||
}
|
||||
else
|
||||
{
|
||||
bool resyncLibTree = false;
|
||||
wxString originalLibNickname = getTargetLib();
|
||||
|
||||
switch( type )
|
||||
{
|
||||
case SAVE_AS_HELPER::SAH_TYPE::REPLACE_TABLE_ENTRY:
|
||||
resyncLibTree = replaceLibTableEntry( originalLibNickname, fn.GetFullPath() );
|
||||
break;
|
||||
|
||||
case SAVE_AS_HELPER::SAH_TYPE::ADD_GLOBAL_TABLE_ENTRY:
|
||||
resyncLibTree = addLibTableEntry( fn.GetFullPath() );
|
||||
break;
|
||||
|
||||
case SAVE_AS_HELPER::SAH_TYPE::ADD_PROJECT_TABLE_ENTRY:
|
||||
resyncLibTree = addLibTableEntry( fn.GetFullPath(), PROJECT_LIB_TABLE );
|
||||
break;
|
||||
|
||||
case SAVE_AS_HELPER::SAH_TYPE::NORMAL_SAVE_AS:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if( resyncLibTree )
|
||||
{
|
||||
FreezeSearchTree();
|
||||
SyncLibraries( true );
|
||||
ThawSearchTree();
|
||||
}
|
||||
}
|
||||
|
||||
ClearMsgPanel();
|
||||
msg.Printf( _( "Symbol library file \"%s\" saved" ), fn.GetFullPath() );
|
||||
|
|
Loading…
Reference in New Issue