Commit 1468a4ae authored by Wayne Stambaugh's avatar Wayne Stambaugh

Pcbnew s-experssion footprint library implementation.

* Add footprint methods to PCB_IO.
* Add FP_CACHE and FP_CACHE_ITEM for handling new footprint library design.
* Add code to save legacy libraries in new format.
* Change behavior of BOARD_ITEM::GetLayerName() to return the default layer
  name when the item does not have a BOARD as a parent.
* Minor changes to the module output formatter when writing to module library
  files (no BOARD as parent).
* Add new (and some that I forgot along the way) CMake flags to
  EDA_BASE_FRAME::CopyVersionInfoToClipboard().
* Add -Wno-narrowing to GCC flags to stop GCC 4.7 from complaining about
  a conversion from int to unsigned in the Boost polygon library.
* Add INPUT_STREAM_READER to richio.cpp to allow using any object derived
  from wxInputStream as a LINE_READER (needs to be validated).
parent 8031e512
...@@ -21,11 +21,14 @@ set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeModules) ...@@ -21,11 +21,14 @@ set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeModules)
# #
option(USE_PCBNEW_SEXPR_FILE_FORMAT option(USE_PCBNEW_SEXPR_FILE_FORMAT
"Use s-expression Pcbnew file format support (default OFF)." ) "Use Pcbnew s-expression file format support (default OFF)." )
option(USE_PCBNEW_NANOMETRES option(USE_PCBNEW_NANOMETRES
"Use nanometers for Pcbnew internal units instead of deci-mils (default OFF).") "Use nanometers for Pcbnew internal units instead of deci-mils (default OFF).")
option(USE_PCBNEW_SEXPR_FOOTPRINT_LIBS
"Use Pcbnew s-expression footprint library format (default OFF).")
# Russian GOST patch # Russian GOST patch
option(wxUSE_UNICODE "enable/disable building unicode (default OFF)") option(wxUSE_UNICODE "enable/disable building unicode (default OFF)")
option(KICAD_GOST "enable/disable building using GOST notation for multiple gates per package (default OFF)") option(KICAD_GOST "enable/disable building using GOST notation for multiple gates per package (default OFF)")
...@@ -100,15 +103,20 @@ endif( USE_PCBNEW_SEXPR_FILE_FORMAT AND NOT USE_PCBNEW_NANOMETRES ) ...@@ -100,15 +103,20 @@ endif( USE_PCBNEW_SEXPR_FILE_FORMAT AND NOT USE_PCBNEW_NANOMETRES )
#================================================ #================================================
if(CMAKE_COMPILER_IS_GNUCXX) if(CMAKE_COMPILER_IS_GNUCXX)
# Added -Wno-narrowing on 10/7/12 to prevent a huge number of warnings when
# compiling with GCC 4.7. This appears to be caused by and int to unsigned
# conversion in the Boost polygon library. At some point in the future when
# Boost is updated to the next version, -Wno-narrowing should be removed to
# see if the problem has been resolved. Wayne.
if(WIN32) # under Windows/mingw, -fPIC option is enabled by default if(WIN32) # under Windows/mingw, -fPIC option is enabled by default
# Set default flags for Release build. # Set default flags for Release build.
set(CMAKE_C_FLAGS_RELEASE "-Wall -O2 -DNDEBUG") set(CMAKE_C_FLAGS_RELEASE "-Wall -Wno-narrowing -O2 -DNDEBUG")
set(CMAKE_CXX_FLAGS_RELEASE "-Wall -O2 -DNDEBUG") set(CMAKE_CXX_FLAGS_RELEASE "-Wall -Wno-narrowing -O2 -DNDEBUG")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-s") set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-s")
# Set default flags for Debug build. # Set default flags for Debug build.
set(CMAKE_C_FLAGS_DEBUG "-Wall -g3 -ggdb3 -DDEBUG") set(CMAKE_C_FLAGS_DEBUG "-Wall -Wno-narrowing -g3 -ggdb3 -DDEBUG")
set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g3 -ggdb3 -DDEBUG") set(CMAKE_CXX_FLAGS_DEBUG "-Wall -Wno-narrowing -g3 -ggdb3 -DDEBUG")
else(WIN32) else(WIN32)
# Set default flags for Release build. # Set default flags for Release build.
set(CMAKE_C_FLAGS_RELEASE "-Wall -O2 -DNDEBUG -fPIC") set(CMAKE_C_FLAGS_RELEASE "-Wall -O2 -DNDEBUG -fPIC")
...@@ -116,8 +124,8 @@ if(CMAKE_COMPILER_IS_GNUCXX) ...@@ -116,8 +124,8 @@ if(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-s") set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-s")
# Set default flags for Debug build. # Set default flags for Debug build.
set(CMAKE_C_FLAGS_DEBUG "-Wall -g3 -ggdb3 -DDEBUG -fPIC") set(CMAKE_C_FLAGS_DEBUG "-Wall -Wno-narrowing -g3 -ggdb3 -DDEBUG -fPIC")
set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g3 -ggdb3 -DDEBUG -fPIC") set(CMAKE_CXX_FLAGS_DEBUG "-Wall -Wno-narrowing -g3 -ggdb3 -DDEBUG -fPIC")
endif(WIN32) endif(WIN32)
endif(CMAKE_COMPILER_IS_GNUCXX) endif(CMAKE_COMPILER_IS_GNUCXX)
......
...@@ -55,8 +55,10 @@ ...@@ -55,8 +55,10 @@
#cmakedefine USE_IMAGES_IN_MENUS 1 #cmakedefine USE_IMAGES_IN_MENUS 1
/// Definitions to enable the s-expression file formats and nanometer units.
#cmakedefine USE_PCBNEW_NANOMETRES #cmakedefine USE_PCBNEW_NANOMETRES
#cmakedefine USE_PCBNEW_SEXPR_FILE_FORMAT #cmakedefine USE_PCBNEW_SEXPR_FILE_FORMAT
#cmakedefine USE_PCBNEW_SEXPR_FOOTPRINT_LIBS
/// The legacy file format revision of the *.brd file created by this build /// The legacy file format revision of the *.brd file created by this build
#if defined(USE_PCBNEW_NANOMETRES) #if defined(USE_PCBNEW_NANOMETRES)
......
...@@ -499,6 +499,27 @@ void EDA_BASE_FRAME::CopyVersionInfoToClipboard( wxCommandEvent& event ) ...@@ -499,6 +499,27 @@ void EDA_BASE_FRAME::CopyVersionInfoToClipboard( wxCommandEvent& event )
tmp << wxT( "Options: " ); tmp << wxT( "Options: " );
tmp << wxT( " USE_PCBNEW_SEXPR_FILE_FORMAT=" );
#ifdef USE_PCBNEW_SEXPR_FILE_FORMAT
tmp << wxT( "ON\n" );
#else
tmp << wxT( "OFF\n" );
#endif
tmp << wxT( " USE_PCBNEW_NANOMETRES=" );
#ifdef USE_PCBNEW_NANOMETRES
tmp << wxT( "ON\n" );
#else
tmp << wxT( "OFF\n" );
#endif
tmp << wxT( " USE_PCBNEW_SEXPR_FOOTPRINT_LIBS=" );
#ifdef USE_PCBNEW_SEXPR_FOOTPRINT_LIBS
tmp << wxT( "ON\n" );
#else
tmp << wxT( "OFF\n" );
#endif
tmp << wxT( " KICAD_GOST=" ); tmp << wxT( " KICAD_GOST=" );
#ifdef KICAD_GOST #ifdef KICAD_GOST
tmp << wxT( "ON\n" ); tmp << wxT( "ON\n" );
......
...@@ -185,6 +185,44 @@ unsigned STRING_LINE_READER::ReadLine() throw( IO_ERROR ) ...@@ -185,6 +185,44 @@ unsigned STRING_LINE_READER::ReadLine() throw( IO_ERROR )
} }
INPUTSTREAM_LINE_READER::INPUTSTREAM_LINE_READER( wxInputStream* aStream ) :
LINE_READER( LINE_READER_LINE_DEFAULT_MAX ),
m_stream( aStream )
{
}
unsigned INPUTSTREAM_LINE_READER::ReadLine() throw( IO_ERROR )
{
length = 0;
line[0] = 0;
while( !m_stream->Eof() )
{
if( length >= maxLineLength )
THROW_IO_ERROR( _( "Maximum line length exceeded" ) );
if( length + 1 > capacity )
expandCapacity( capacity * 2 );
line[ length ] = m_stream->GetC();
length++;
if( line[ length - 1 ] == '\n' )
break;
}
line[ length ] = 0;
length -= 1;
// lineNum is incremented even if there was no line read, because this
// leads to better error reporting when we hit an end of file.
++lineNum;
return length;
}
//-----<OUTPUTFORMATTER>---------------------------------------------------- //-----<OUTPUTFORMATTER>----------------------------------------------------
// factor out a common GetQuoteChar // factor out a common GetQuoteChar
......
...@@ -51,6 +51,7 @@ const wxString DrillFileExtension( wxT( "drl" ) ); ...@@ -51,6 +51,7 @@ const wxString DrillFileExtension( wxT( "drl" ) );
const wxString SVGFileExtension( wxT( "svg" ) ); const wxString SVGFileExtension( wxT( "svg" ) );
const wxString ReportFileExtension( wxT( "rpt" ) ); const wxString ReportFileExtension( wxT( "rpt" ) );
const wxString FootprintPlaceFileExtension( wxT( "pos" ) ); const wxString FootprintPlaceFileExtension( wxT( "pos" ) );
const wxString FootprintFileExtension( wxT( "kicad_mod" ) );
// These strings are wildcards for file selection dialogs. // These strings are wildcards for file selection dialogs.
// Because thes are static, one should explicitely call wxGetTranslation // Because thes are static, one should explicitely call wxGetTranslation
...@@ -64,7 +65,8 @@ const wxString GerberFileWildcard( _( "Gerber files (*.pho)|*.pho" ) ); ...@@ -64,7 +65,8 @@ const wxString GerberFileWildcard( _( "Gerber files (*.pho)|*.pho" ) );
const wxString LegacyPcbFileWildcard( _( "KiCad printed circuit board files (*.brd)|*.brd" ) ); const wxString LegacyPcbFileWildcard( _( "KiCad printed circuit board files (*.brd)|*.brd" ) );
const wxString EaglePcbFileWildcard( _( "Eagle ver. 6.x XML PCB files (*.brd)|*.brd" ) ); const wxString EaglePcbFileWildcard( _( "Eagle ver. 6.x XML PCB files (*.brd)|*.brd" ) );
const wxString PcbFileWildcard( _( "KiCad s-expr printed circuit board files (*.kicad_pcb)|*.kicad_pcb" ) ); const wxString PcbFileWildcard( _( "KiCad s-expr printed circuit board files (*.kicad_pcb)|*.kicad_pcb" ) );
const wxString FootprintLibFileWildcard( _( "KiCad footprint library file (*.mod)|*.mod" ) ); const wxString FootprintLibFileWildcard( _( "KiCad footprint s-expre library file (*.kicad_mod)|*.kicad_mod" ) );
const wxString LegacyFootprintLibFileWildcard( _( "KiCad footprint library file (*.mod)|*.mod" ) );
const wxString PdfFileWildcard( _( "Portable document format files (*.pdf)|*.pdf" ) ); const wxString PdfFileWildcard( _( "Portable document format files (*.pdf)|*.pdf" ) );
const wxString MacrosFileWildcard( _( "KiCad recorded macros (*.mcr)|*.mcr" ) ); const wxString MacrosFileWildcard( _( "KiCad recorded macros (*.mcr)|*.mcr" ) );
const wxString AllFilesWildcard( _( "All files (*)|*" ) ); const wxString AllFilesWildcard( _( "All files (*)|*" ) );
......
...@@ -384,6 +384,28 @@ public: ...@@ -384,6 +384,28 @@ public:
}; };
/**
* Class INPUTSTREAM_LINE_READER
* is a LINE_READER that reads from a wxInputStream object.
*/
class INPUTSTREAM_LINE_READER : public LINE_READER
{
protected:
wxInputStream* m_stream; //< The input stream to read. No ownership of this pointer.
public:
/**
* Constructor WXINPUTSTREAM_LINE_READER
*
* @param aStream A pointer to a wxInputStream object to read.
*/
INPUTSTREAM_LINE_READER( wxInputStream* aStream );
unsigned ReadLine() throw( IO_ERROR ); // see LINE_READER::ReadLine() description
};
/** /**
* Class OUTPUTFORMATTER * Class OUTPUTFORMATTER
* is an important interface (abstract) class used to output UTF8 text in * is an important interface (abstract) class used to output UTF8 text in
......
...@@ -60,6 +60,7 @@ extern const wxString DrillFileExtension; ...@@ -60,6 +60,7 @@ extern const wxString DrillFileExtension;
extern const wxString SVGFileExtension; extern const wxString SVGFileExtension;
extern const wxString ReportFileExtension; extern const wxString ReportFileExtension;
extern const wxString FootprintPlaceFileExtension; extern const wxString FootprintPlaceFileExtension;
extern const wxString FootprintFileExtension;
/// Proper wxFileDialog wild card definitions. /// Proper wxFileDialog wild card definitions.
extern const wxString SchematicSymbolFileWildcard; extern const wxString SchematicSymbolFileWildcard;
...@@ -82,6 +83,7 @@ extern const wxString ReportFileWildcard; ...@@ -82,6 +83,7 @@ extern const wxString ReportFileWildcard;
extern const wxString FootprintPlaceFileWildcard; extern const wxString FootprintPlaceFileWildcard;
extern const wxString VrmlFileWildcard; extern const wxString VrmlFileWildcard;
extern const wxString DocModulesFileName; extern const wxString DocModulesFileName;
extern const wxString LegacyFootprintLibFileWildcard;
extern const wxString FootprintLibFileWildcard; extern const wxString FootprintLibFileWildcard;
#endif // INCLUDE_WILDCARDS_AND_FILES_EXT_H_ #endif // INCLUDE_WILDCARDS_AND_FILES_EXT_H_
...@@ -369,24 +369,25 @@ public: ...@@ -369,24 +369,25 @@ public:
bool aPadShapeFilter, bool aPadShapeFilter,
bool aPadOrientFilter, bool aPadOrientFilter,
bool aPadLayerFilter, bool aPadLayerFilter,
bool aRedraw, bool aSaveForUndo ); bool aRedraw,
bool aSaveForUndo );
// loading footprints // loading footprints
/** /**
* Function loadFootprintFromLibrary * Function loadFootprintFromLibrary
* loads @a aFootprintName from @a aLibraryPath. * loads @a aFootprintName from @a aLibraryPath.
* If found add the module is also added to the BOARD, just for good measure.
* *
* @param aLibraryPath - the full filename or the short name of the library to read. * @param aLibraryPath - the full filename or the short name of the library to read.
* if it is a short name, the file is searched in all library valid paths * if it is a short name, the file is searched in all library valid paths
* @param aFootprintName is the footprint to load * @param aFootprintName is the footprint to load
* @param aDisplayError = true to display an error message if any. * @param aDisplayError = true to display an error message if any.
* @param aAddToBoard Set to true to add the footprint to the board if found.
* *
* @return MODULE* - new module, or NULL * @return MODULE* - new module, or NULL
*/ */
MODULE* loadFootprintFromLibrary( const wxString& aLibraryPath, MODULE* loadFootprintFromLibrary( const wxString& aLibraryPath, const wxString& aFootprintName,
const wxString& aFootprintName, bool aDisplayError ); bool aDisplayError, bool aAddToBoard = true );
/** /**
* Function loadFootprintFromLibraries * Function loadFootprintFromLibraries
......
...@@ -82,10 +82,8 @@ wxString BOARD_ITEM::GetLayerName() const ...@@ -82,10 +82,8 @@ wxString BOARD_ITEM::GetLayerName() const
if( board != NULL ) if( board != NULL )
return board->GetLayerName( m_Layer ).Trim(); return board->GetLayerName( m_Layer ).Trim();
wxFAIL_MSG( wxT( "No board found for board item type " ) + GetClass() ); // If no parent, return the default layer for the object.
layerName = _( "** undefined layer **" ); return BOARD::GetDefaultLayerName( m_Layer, true );
return layerName;
} }
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <build_version.h> // LEGACY_BOARD_FILE_VERSION #include <build_version.h> // LEGACY_BOARD_FILE_VERSION
#include <macros.h> #include <macros.h>
#include <3d_struct.h> #include <3d_struct.h>
#include <wildcards_and_files_ext.h>
#include <class_board.h> #include <class_board.h>
#include <class_module.h> #include <class_module.h>
...@@ -44,11 +45,258 @@ ...@@ -44,11 +45,258 @@
#include <kicad_plugin.h> #include <kicad_plugin.h>
#include <pcb_parser.h> #include <pcb_parser.h>
#include <wx/dir.h>
#include <wx/filename.h>
#include <wx/wfstream.h> #include <wx/wfstream.h>
#include <boost/ptr_container/ptr_map.hpp>
#include <memory.h>
using namespace std;
#define FMTIU BOARD_ITEM::FormatInternalUnits #define FMTIU BOARD_ITEM::FormatInternalUnits
/**
* Class FP_CACHE_ITEM
* is helper class for creating a footprint library cache.
*
* The new footprint library design is a file path of individual module files
* that contain a single module per file. This class is a helper only for the
* footprint portion of the PLUGIN API, and only for the #PCB_IO plugin. It is
* private to this implementation file so it is not placed into a header.
*/
class FP_CACHE_ITEM
{
wxFileName m_file_name; /// The the full file name and path of the footprint to cache.
bool m_writable; /// Writability status of the footprint file.
wxDateTime m_mod_time; /// The last file modified time stamp.
auto_ptr< MODULE > m_module;
public:
FP_CACHE_ITEM( MODULE* aModule, const wxFileName& aFileName );
wxString GetName() const { return m_file_name.GetDirs().Last(); }
wxFileName GetFileName() const { return m_file_name; }
bool IsModified() const;
MODULE* GetModule() const { return m_module.get(); }
void UpdateModificationTime() { m_mod_time = m_file_name.GetModificationTime(); }
};
FP_CACHE_ITEM::FP_CACHE_ITEM( MODULE* aModule, const wxFileName& aFileName )
{
m_file_name = aFileName;
auto_ptr< MODULE > tmp( aModule );
m_module = tmp;
m_mod_time.Now();
}
bool FP_CACHE_ITEM::IsModified() const
{
return m_file_name.GetModificationTime() != m_mod_time;
}
typedef boost::ptr_map< std::string, FP_CACHE_ITEM > MODULE_MAP;
typedef MODULE_MAP::iterator MODULE_ITER;
typedef MODULE_MAP::const_iterator MODULE_CITER;
class FP_CACHE
{
PCB_IO* m_owner; /// Plugin object that owns the cache.
wxFileName m_lib_path; /// The path of the library.
wxDateTime m_mod_time; /// Footprint library path modified time stamp.
MODULE_MAP m_modules; /// Map of footprint file name per MODULE*.
public:
FP_CACHE( PCB_IO* aOwner, const wxString& aLibraryPath );
wxString GetPath() const { return m_lib_path.GetPath(); }
wxDateTime GetLastModificationTime() const { return m_mod_time; }
bool IsWritable() const { return m_lib_path.IsOk() && m_lib_path.IsDirWritable(); }
MODULE_MAP& GetModules() { return m_modules; }
// Most all functions in this class throw IO_ERROR exceptions. There are no
// error codes nor user interface calls from here, nor in any PLUGIN.
// Catch these exceptions higher up please.
/// save the entire legacy library to m_lib_name;
void Save();
void Load();
void Remove( const wxString& aFootprintName );
wxDateTime GetLibModificationTime();
bool IsModified();
};
FP_CACHE::FP_CACHE( PCB_IO* aOwner, const wxString& aLibraryPath )
{
m_owner = aOwner;
m_lib_path.SetPath( aLibraryPath );
}
wxDateTime FP_CACHE::GetLibModificationTime()
{
return m_lib_path.GetModificationTime();
}
void FP_CACHE::Save()
{
if( !m_lib_path.DirExists() && !m_lib_path.Mkdir() )
{
THROW_IO_ERROR( wxString::Format( _( "Cannot create footprint library path '%s'." ),
m_lib_path.GetPath().GetData() ) );
}
if( !m_lib_path.IsDirWritable() )
{
THROW_IO_ERROR( wxString::Format( _( "Footprint library path '%s' is read only" ),
GetChars( m_lib_path.GetPath() ) ) );
}
for( MODULE_ITER it = m_modules.begin(); it != m_modules.end(); ++it )
{
wxFileName fn = it->second->GetFileName();
if( fn.FileExists() && !it->second->IsModified() )
continue;
wxString tempFileName = fn.CreateTempFileName( fn.GetPath() );
// Allow file output stream to go out of scope to close the file stream before
// renaming the file.
{
wxLogDebug( wxT( "Creating temporary library file %s" ), GetChars( tempFileName ) );
wxFFileOutputStream os( tempFileName );
if( !os.IsOk() )
{
THROW_IO_ERROR( wxString::Format( _( "cannot save footprint library file '%s'" ),
tempFileName.GetData() ) );
}
STREAM_OUTPUTFORMATTER formatter( os );
m_owner->SetOutputFormatter( &formatter );
m_owner->Format( (BOARD_ITEM*) it->second->GetModule() );
}
wxRemove( fn.GetFullPath() ); // it is not an error if this does not exist
if( wxRename( tempFileName, fn.GetFullPath() ) )
{
THROW_IO_ERROR( wxString::Format( _( "cannot rename temporary file '%s' to footprint library file '%s'" ),
tempFileName.GetData(),
fn.GetFullPath().GetData() ) );
}
it->second->UpdateModificationTime();
m_mod_time = GetLibModificationTime();
}
}
void FP_CACHE::Load()
{
wxDir dir( m_lib_path.GetPath() );
if( !dir.IsOpened() )
{
THROW_IO_ERROR( wxString::Format( _( "footprint library path '%s' does not exist" ),
m_lib_path.GetPath().GetData() ) );
}
wxString fpFileName;
wxString wildcard = wxT( "*." ) + FootprintFileExtension;
if( !dir.GetFirst( &fpFileName, wildcard, wxDIR_FILES ) )
return;
do
{
FILE* fp = wxFopen( fpFileName, wxT( "r" ) );
if( !fp )
{
THROW_IO_ERROR( wxString::Format( _( "cannot open footprint library file '%s'" ),
fpFileName.GetData() ) );
}
// reader now owns fp, will close on exception or return
PCB_PARSER parser( new FILE_LINE_READER( fp, fpFileName ) );
std::string name = TO_UTF8( fpFileName );
m_modules.insert( name, new FP_CACHE_ITEM( (MODULE*) parser.Parse(), fpFileName ) );
} while( dir.GetNext( &fpFileName ) );
// Remember the file modification time of library file when the
// cache snapshot was made, so that in a networked environment we will
// reload the cache as needed.
m_mod_time = GetLibModificationTime();
}
void FP_CACHE::Remove( const wxString& aFootprintName )
{
std::string footprintName = TO_UTF8( aFootprintName );
MODULE_CITER it = m_modules.find( footprintName );
if( it == m_modules.end() )
{
THROW_IO_ERROR( wxString::Format( _( "library '%s' has no footprint '%s' to delete" ),
m_lib_path.GetPath().GetData(),
aFootprintName.GetData() ) );
}
// Remove the module from the cache and delete the module file from the library.
wxString fullPath = it->second->GetFileName().GetFullPath();
m_modules.erase( footprintName );
wxRemoveFile( fullPath );
}
bool FP_CACHE::IsModified()
{
if( !m_lib_path.DirExists() )
return true;
for( MODULE_ITER it = m_modules.begin(); it != m_modules.end(); ++it )
{
wxFileName fn = it->second->GetFileName();
if( !fn.FileExists() )
{
wxLogDebug( wxT( "Footprint cache file '%s' does not exist." ),
fn.GetFullPath().GetData() );
return true;
}
if( it->second->IsModified() )
{
wxLogDebug( wxT( "Footprint cache file '%s' has been modified." ),
fn.GetFullPath().GetData() );
return true;
}
}
return false;
}
void PCB_IO::Save( const wxString& aFileName, BOARD* aBoard, PROPERTIES* aProperties ) void PCB_IO::Save( const wxString& aFileName, BOARD* aBoard, PROPERTIES* aProperties )
{ {
LOCALE_IO toggle; // toggles on, then off, the C locale. LOCALE_IO toggle; // toggles on, then off, the C locale.
...@@ -779,13 +1027,23 @@ void PCB_IO::format( D_PAD* aPad, int aNestLevel ) const ...@@ -779,13 +1027,23 @@ void PCB_IO::format( D_PAD* aPad, int aNestLevel ) const
m_out->Print( aNestLevel+1, "(layers" ); m_out->Print( aNestLevel+1, "(layers" );
unsigned layerMask = aPad->GetLayerMask() & m_board->GetEnabledLayers(); unsigned layerMask = aPad->GetLayerMask();
if( m_board )
layerMask &= m_board->GetEnabledLayers();
for( int layer = 0; layerMask; ++layer, layerMask >>= 1 ) for( int layer = 0; layerMask; ++layer, layerMask >>= 1 )
{ {
if( layerMask & 1 ) if( layerMask & 1 )
{ {
m_out->Print( 0, " %s", m_out->Quotew( m_board->GetLayerName( layer ) ).c_str() ); wxString layerName;
if( m_board )
layerName = m_board->GetLayerName( layer );
else
layerName = BOARD::GetDefaultLayerName( layer, true );
m_out->Print( 0, " %s", m_out->Quotew(layerName ).c_str() );
} }
} }
...@@ -1185,12 +1443,19 @@ void PCB_IO::format( ZONE_CONTAINER* aZone, int aNestLevel ) const ...@@ -1185,12 +1443,19 @@ void PCB_IO::format( ZONE_CONTAINER* aZone, int aNestLevel ) const
} }
PCB_IO::PCB_IO() PCB_IO::PCB_IO() :
m_cache( 0 )
{ {
m_out = &m_sf; m_out = &m_sf;
} }
PCB_IO::~PCB_IO()
{
delete m_cache;
}
BOARD* PCB_IO::Load( const wxString& aFileName, BOARD* aAppendToMe, PROPERTIES* aProperties ) BOARD* PCB_IO::Load( const wxString& aFileName, BOARD* aAppendToMe, PROPERTIES* aProperties )
{ {
wxFFile file( aFileName, wxT("r") ); wxFFile file( aFileName, wxT("r") );
...@@ -1210,5 +1475,252 @@ BOARD* PCB_IO::Load( const wxString& aFileName, BOARD* aAppendToMe, PROPERTIES* ...@@ -1210,5 +1475,252 @@ BOARD* PCB_IO::Load( const wxString& aFileName, BOARD* aAppendToMe, PROPERTIES*
// Give the filename to the board if it's new // Give the filename to the board if it's new
if( !aAppendToMe ) if( !aAppendToMe )
board->SetFileName( aFileName ); board->SetFileName( aFileName );
return board; return board;
} }
void PCB_IO::init( PROPERTIES* aProperties )
{
m_board = NULL;
m_props = aProperties;
}
void PCB_IO::cacheLib( const wxString& aLibraryPath )
{
if( !m_cache || m_cache->GetPath() != aLibraryPath || m_cache->IsModified() )
{
// a spectacular episode in memory management:
delete m_cache;
m_cache = new FP_CACHE( this, aLibraryPath );
m_cache->Load();
}
}
wxArrayString PCB_IO::FootprintEnumerate( const wxString& aLibraryPath, PROPERTIES* aProperties )
{
LOCALE_IO toggle; // toggles on, then off, the C locale.
init( aProperties );
cacheLib( aLibraryPath );
const MODULE_MAP& mods = m_cache->GetModules();
wxArrayString ret;
for( MODULE_CITER it = mods.begin(); it != mods.end(); ++it )
{
ret.Add( FROM_UTF8( it->first.c_str() ) );
}
return ret;
}
MODULE* PCB_IO::FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName,
PROPERTIES* aProperties )
{
LOCALE_IO toggle; // toggles on, then off, the C locale.
init( aProperties );
cacheLib( aLibraryPath );
const MODULE_MAP& mods = m_cache->GetModules();
MODULE_CITER it = mods.find( TO_UTF8( aFootprintName ) );
if( it == mods.end() )
{
return NULL;
}
// copy constructor to clone the already loaded MODULE
return new MODULE( *it->second->GetModule() );
}
void PCB_IO::FootprintSave( const wxString& aLibraryPath, const MODULE* aFootprint,
PROPERTIES* aProperties )
{
LOCALE_IO toggle; // toggles on, then off, the C locale.
init( aProperties );
cacheLib( aLibraryPath );
if( !m_cache->IsWritable() )
{
THROW_IO_ERROR( wxString::Format( _( "Library '%s' is read only" ),
aLibraryPath.GetData() ) );
}
std::string footprintName = TO_UTF8( aFootprint->GetLibRef() );
MODULE_MAP& mods = m_cache->GetModules();
// Quietly overwrite module and delete module file from path for any by same name.
wxFileName fn( aLibraryPath, aFootprint->GetLibRef(), FootprintFileExtension );
if( !fn.IsOk() )
{
THROW_IO_ERROR( wxString::Format( _( "Footprint file name '%s' is not valid." ),
GetChars( fn.GetFullPath() ) ) );
}
if( fn.FileExists() && !fn.IsFileWritable() )
{
THROW_IO_ERROR( wxString::Format( _( "user does not have write permission to delete file '%s' " ),
GetChars( fn.GetFullPath() ) ) );
}
MODULE_CITER it = mods.find( footprintName );
if( it != mods.end() )
{
wxLogDebug( wxT( "Removing footprint library file '%s'." ), fn.GetFullPath().GetData() );
mods.erase( footprintName );
wxRemoveFile( fn.GetFullPath() );
}
// I need my own copy for the cache
MODULE* module = new MODULE( *aFootprint );
// and it's time stamp must be 0, it should have no parent, orientation should
// be zero, and it should be on the front layer.
module->SetTimeStamp( 0 );
module->SetParent( 0 );
module->SetOrientation( 0 );
if( module->GetLayer() != LAYER_N_FRONT )
module->Flip( module->GetPosition() );
wxLogDebug( wxT( "Creating s-expression footprint file: %s." ), fn.GetFullPath().GetData() );
mods.insert( footprintName, new FP_CACHE_ITEM( module, fn ) );
m_cache->Save();
}
void PCB_IO::FootprintDelete( const wxString& aLibraryPath, const wxString& aFootprintName )
{
LOCALE_IO toggle; // toggles on, then off, the C locale.
init( NULL );
cacheLib( aLibraryPath );
if( !m_cache->IsWritable() )
{
THROW_IO_ERROR( wxString::Format( _( "Library '%s' is read only" ),
aLibraryPath.GetData() ) );
}
m_cache->Remove( aFootprintName );
}
void PCB_IO::FootprintLibCreate( const wxString& aLibraryPath, PROPERTIES* aProperties )
{
if( wxDir::Exists( aLibraryPath ) )
{
THROW_IO_ERROR( wxString::Format( _( "cannot overwrite library path '%s'" ),
aLibraryPath.GetData() ) );
}
LOCALE_IO toggle;
init( aProperties );
delete m_cache;
m_cache = new FP_CACHE( this, aLibraryPath );
m_cache->Save();
}
void PCB_IO::FootprintLibDelete( const wxString& aLibraryPath, PROPERTIES* aProperties )
{
wxFileName fn;
fn.SetPath( aLibraryPath );
// Return if there is no library path to delete.
if( !fn.DirExists() )
return;
if( !fn.IsDirWritable() )
{
THROW_IO_ERROR( wxString::Format( _( "user does not have permission to delete directory '%s'" ),
aLibraryPath.GetData() ) );
}
wxDir dir( aLibraryPath );
if( dir.HasSubDirs() )
{
THROW_IO_ERROR( wxString::Format( _( "library directory '%s' has unexpected sub-directories" ),
aLibraryPath.GetData() ) );
}
// All the footprint files must be deleted before the directory can be deleted.
if( dir.HasFiles() )
{
unsigned i;
wxFileName tmp;
wxArrayString files;
wxDir::GetAllFiles( aLibraryPath, &files );
for( i = 0; i < files.GetCount(); i++ )
{
tmp = files[i];
if( tmp.GetExt() != FootprintFileExtension )
{
THROW_IO_ERROR( wxString::Format( _( "unexpected file '%s' has found in library path '%'" ),
files[i].GetData(), aLibraryPath.GetData() ) );
}
}
for( i = 0; i < files.GetCount(); i++ )
{
wxRemoveFile( files[i] );
}
}
wxLogDebug( wxT( "Removing footprint library '%s'" ), aLibraryPath.GetData() );
// Some of the more elaborate wxRemoveFile() crap puts up its own wxLog dialog
// we don't want that. we want bare metal portability with no UI here.
if( !wxRmdir( aLibraryPath ) )
{
THROW_IO_ERROR( wxString::Format( _( "footprint library '%s' cannot be deleted" ),
aLibraryPath.GetData() ) );
}
// For some reason removing a directory in Windows is not immediately updated. This delay
// prevents an error when attempting to immediately recreate the same directory when over
// writing an existing library.
#ifdef __WINDOWS__
wxMilliSleep( 250L );
#endif
if( m_cache && m_cache->GetPath() == aLibraryPath )
{
delete m_cache;
m_cache = NULL;
}
}
bool PCB_IO::IsFootprintLibWritable( const wxString& aLibraryPath )
{
LOCALE_IO toggle;
init( NULL );
cacheLib( aLibraryPath );
return m_cache->IsWritable();
}
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
class BOARD; class BOARD;
class BOARD_ITEM; class BOARD_ITEM;
class FP_CACHE;
/** Current s-expression file format version. 2 was the last legacy format version. */ /** Current s-expression file format version. 2 was the last legacy format version. */
...@@ -68,10 +69,28 @@ public: ...@@ -68,10 +69,28 @@ public:
BOARD* Load( const wxString& aFileName, BOARD* aAppendToMe, PROPERTIES* aProperties = NULL ); BOARD* Load( const wxString& aFileName, BOARD* aAppendToMe, PROPERTIES* aProperties = NULL );
wxArrayString FootprintEnumerate( const wxString& aLibraryPath, PROPERTIES* aProperties = NULL);
MODULE* FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName,
PROPERTIES* aProperties = NULL );
void FootprintSave( const wxString& aLibraryPath, const MODULE* aFootprint,
PROPERTIES* aProperties = NULL );
void FootprintDelete( const wxString& aLibraryPath, const wxString& aFootprintName );
void FootprintLibCreate( const wxString& aLibraryPath, PROPERTIES* aProperties = NULL);
void FootprintLibDelete( const wxString& aLibraryPath, PROPERTIES* aProperties = NULL );
bool IsFootprintLibWritable( const wxString& aLibraryPath );
//-----</PLUGIN API>-------------------------------------------------------- //-----</PLUGIN API>--------------------------------------------------------
PCB_IO(); PCB_IO();
~PCB_IO();
/** /**
* Function Format * Function Format
* outputs \a aItem to \a aFormatter in s-expression format. * outputs \a aItem to \a aFormatter in s-expression format.
...@@ -92,17 +111,19 @@ public: ...@@ -92,17 +111,19 @@ public:
return ret; return ret;
} }
void SetOutputFormatter( OUTPUTFORMATTER* aFormatter ) { m_out = aFormatter; }
protected: protected:
wxString m_error; ///< for throwing exceptions wxString m_error; ///< for throwing exceptions
BOARD* m_board; ///< which BOARD, no ownership here BOARD* m_board; ///< which BOARD, no ownership here
PROPERTIES* m_props; ///< passed via Save() or Load(), no ownership, may be NULL. PROPERTIES* m_props; ///< passed via Save() or Load(), no ownership, may be NULL.
FP_CACHE* m_cache; ///< Footprint library cache.
LINE_READER* m_reader; ///< no ownership here. LINE_READER* m_reader; ///< no ownership here.
wxString m_filename; ///< for saves only, name is in m_reader for loads wxString m_filename; ///< for saves only, name is in m_reader for loads
int m_loading_format_version; ///< which BOARD_FORMAT_VERSION am I Load()ing? int m_loading_format_version; ///< which #BOARD_FORMAT_VERSION should be Load()ed?
STRING_FORMATTER m_sf; STRING_FORMATTER m_sf;
OUTPUTFORMATTER* m_out; ///< output any Format()s to this, no ownership OUTPUTFORMATTER* m_out; ///< output any Format()s to this, no ownership
...@@ -144,6 +165,11 @@ private: ...@@ -144,6 +165,11 @@ private:
throw( IO_ERROR ); throw( IO_ERROR );
void formatLayer( const BOARD_ITEM* aItem ) const; void formatLayer( const BOARD_ITEM* aItem ) const;
/// we only cache one footprint library for now, this determines which one.
void cacheLib( const wxString& aLibraryPath );
void init( PROPERTIES* aProperties );
}; };
#endif // KICAD_PLUGIN_H_ #endif // KICAD_PLUGIN_H_
...@@ -4387,4 +4387,3 @@ LEGACY_PLUGIN::~LEGACY_PLUGIN() ...@@ -4387,4 +4387,3 @@ LEGACY_PLUGIN::~LEGACY_PLUGIN()
{ {
delete m_cache; delete m_cache;
} }
...@@ -163,7 +163,7 @@ void FOOTPRINT_EDIT_FRAME::Export_Module( MODULE* aModule, bool aCreateSysLib ) ...@@ -163,7 +163,7 @@ void FOOTPRINT_EDIT_FRAME::Export_Module( MODULE* aModule, bool aCreateSysLib )
config->Read( EXPORT_IMPORT_LASTPATH_KEY, &path ); config->Read( EXPORT_IMPORT_LASTPATH_KEY, &path );
title = aCreateSysLib ? _( "Create New Library" ) : _( "Export Module" ); title = aCreateSysLib ? _( "Create New Library" ) : _( "Export Module" );
wildcard = aCreateSysLib ? FootprintLibFileWildcard : ModExportFileWildcard; wildcard = aCreateSysLib ? LegacyFootprintLibFileWildcard : ModExportFileWildcard;
fn.SetPath( path ); fn.SetPath( path );
...@@ -272,7 +272,7 @@ void PCB_EDIT_FRAME::ArchiveModulesOnBoard( const wxString& aLibName, bool aNewM ...@@ -272,7 +272,7 @@ void PCB_EDIT_FRAME::ArchiveModulesOnBoard( const wxString& aLibName, bool aNewM
{ {
wxFileDialog dlg( this, _( "Library" ), path, wxFileDialog dlg( this, _( "Library" ), path,
wxEmptyString, wxEmptyString,
wxGetTranslation( FootprintLibFileWildcard ), wxGetTranslation( LegacyFootprintLibFileWildcard ),
wxFD_SAVE ); wxFD_SAVE );
if( dlg.ShowModal() == wxID_CANCEL ) if( dlg.ShowModal() == wxID_CANCEL )
...@@ -562,4 +562,3 @@ int FOOTPRINT_EDIT_FRAME::CreateLibrary( const wxString& aLibName ) ...@@ -562,4 +562,3 @@ int FOOTPRINT_EDIT_FRAME::CreateLibrary( const wxString& aLibName )
return 1; // remember how many times we succeeded return 1; // remember how many times we succeeded
} }
...@@ -284,7 +284,9 @@ MODULE* PCB_BASE_FRAME::GetModuleLibrary( const wxString& aLibraryPath, ...@@ -284,7 +284,9 @@ MODULE* PCB_BASE_FRAME::GetModuleLibrary( const wxString& aLibraryPath,
* if it is a short name, the file is searched in all library valid paths * if it is a short name, the file is searched in all library valid paths
*/ */
MODULE* PCB_BASE_FRAME::loadFootprintFromLibrary( const wxString& aLibraryPath, MODULE* PCB_BASE_FRAME::loadFootprintFromLibrary( const wxString& aLibraryPath,
const wxString& aFootprintName, bool aDisplayError ) const wxString& aFootprintName,
bool aDisplayError,
bool aAddToBoard )
{ {
try try
{ {
...@@ -309,7 +311,9 @@ MODULE* PCB_BASE_FRAME::loadFootprintFromLibrary( const wxString& aLibraryPath, ...@@ -309,7 +311,9 @@ MODULE* PCB_BASE_FRAME::loadFootprintFromLibrary( const wxString& aLibraryPath,
return NULL; return NULL;
} }
if( aAddToBoard )
GetBoard()->Add( footprint, ADD_APPEND ); GetBoard()->Add( footprint, ADD_APPEND );
SetStatusText( wxEmptyString ); SetStatusText( wxEmptyString );
return footprint; return footprint;
} }
...@@ -509,3 +513,86 @@ MODULE* FOOTPRINT_EDIT_FRAME::Select_1_Module_From_BOARD( BOARD* aPcb ) ...@@ -509,3 +513,86 @@ MODULE* FOOTPRINT_EDIT_FRAME::Select_1_Module_From_BOARD( BOARD* aPcb )
return module; return module;
} }
void FOOTPRINT_EDIT_FRAME::OnSaveLibraryAs( wxCommandEvent& aEvent )
{
wxFileName fn;
wxString msg, path, title;
FOOTPRINT_LIST fpInfoList;
title = _( "Save Footprint Library As" );
fn = wxFileName( wxEmptyString, GetCurrentLib(), FootprintLibFileExtension );
path = wxGetApp().FindLibraryPath( fn );
fn.SetPath( path );
wxDirDialog dlg( this, msg, fn.GetPath() );
if( dlg.ShowModal() == wxID_CANCEL )
return;
fn.SetPath( dlg.GetPath() );
fn.AppendDir( GetCurrentLib() );
path = fn.GetPath();
try
{
// @todo : hard code this as IO_MGR::KICAD plugin, what would be the reason to "export"
// any other single footprint type, with clipboard support coming?
// Use IO_MGR::LEGACY for now, until the IO_MGR::KICAD plugin is ready.
PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::KICAD ) );
try
{
// try to delete the library whether it exists or not, quietly.
pi->FootprintLibDelete( fn.GetPath() );
}
catch( IO_ERROR ioe )
{
// Ignore this, it will often happen and is not an error because
// the library may not exist. If library was in a read only directory,
// it will still exist as we get to the FootprintLibCreate() below.
}
pi->FootprintLibCreate( fn.GetPath() );
wxArrayString libNameList;
wxLogDebug( wxT( "Loading legacy footprint library '%s'." ), m_CurrentLib.GetData() );
wxFileName libFileName = m_CurrentLib;
libFileName.SetExt( FootprintLibFileExtension );
wxString libPath = wxGetApp().FindLibraryPath( libFileName );
libNameList.Add( m_CurrentLib );
fpInfoList.ReadFootprintFiles( libNameList );
for( unsigned i = 0; i < fpInfoList.GetCount(); i++ )
{
MODULE* module = loadFootprintFromLibrary( libFileName.GetFullPath(),
fpInfoList.GetItem( i ).m_Module,
true, false );
wxLogDebug( wxT( "Saving footprint %s as s-expression to path %s" ),
module->GetLibRef().GetData(), path.GetData() );
pi->FootprintSave( path, module );
}
}
catch( IO_ERROR ioe )
{
DisplayError( this, ioe.errorText );
return;
}
msg.Printf( _( "Footprint library type '%s' saved to <%s> as s-expression" ),
GetCurrentLib().GetData(), path.GetData() );
DisplayInfoMessage( this, msg );
}
...@@ -76,19 +76,19 @@ void FOOTPRINT_EDIT_FRAME::ReCreateMenuBar() ...@@ -76,19 +76,19 @@ void FOOTPRINT_EDIT_FRAME::ReCreateMenuBar()
// from File // from File
AddMenuItem( openSubmenu, ID_MODEDIT_IMPORT_PART, AddMenuItem( openSubmenu, ID_MODEDIT_IMPORT_PART,
_( "Load from File (&Import)" ), _( "Import Module from File (&Import)" ),
_( "Import a footprint from an existing file" ), _( "Import a footprint from an existing file" ),
KiBitmap( import_module_xpm ) ); KiBitmap( import_module_xpm ) );
// from Library // from Library
AddMenuItem( openSubmenu, ID_MODEDIT_LOAD_MODULE, AddMenuItem( openSubmenu, ID_MODEDIT_LOAD_MODULE,
_( "Load from Li&brary" ), _( "Load Module from Current Li&brary" ),
_( "Open a footprint module from a Library" ), _( "Open a footprint module from a Library" ),
KiBitmap( module_xpm ) ); KiBitmap( module_xpm ) );
// from current Board // from current Board
AddMenuItem( openSubmenu, ID_MODEDIT_LOAD_MODULE_FROM_BOARD, AddMenuItem( openSubmenu, ID_MODEDIT_LOAD_MODULE_FROM_BOARD,
_( "Load from &Current Board" ), _( "Load Module from &Current Board" ),
_( "Load a footprint module from the current loaded board" ), _( "Load a footprint module from the current loaded board" ),
KiBitmap( load_module_board_xpm ) ); KiBitmap( load_module_board_xpm ) );
...@@ -99,6 +99,13 @@ void FOOTPRINT_EDIT_FRAME::ReCreateMenuBar() ...@@ -99,6 +99,13 @@ void FOOTPRINT_EDIT_FRAME::ReCreateMenuBar()
KiBitmap( open_document_xpm ) ); KiBitmap( open_document_xpm ) );
fileMenu->AppendSeparator(); fileMenu->AppendSeparator();
#ifdef USE_PCBNEW_SEXPR_FOOTPRINT_LIBS
// Save the currently loaded legacy library as an s-expression library.
AddMenuItem( fileMenu, ID_MODEDIT_SAVE_LIBRARY_AS, _( "Save Library In S-Expression Format" ),
_( "Save currently loaded legacy library as an s-expression library." ),
wxNullBitmap );
#endif
// Save module // Save module
text = AddHotkeyName( _( "&Save Module in Active Library" ), text = AddHotkeyName( _( "&Save Module in Active Library" ),
g_Module_Editor_Hokeys_Descr, HK_SAVE_MODULE ); g_Module_Editor_Hokeys_Descr, HK_SAVE_MODULE );
...@@ -108,7 +115,7 @@ void FOOTPRINT_EDIT_FRAME::ReCreateMenuBar() ...@@ -108,7 +115,7 @@ void FOOTPRINT_EDIT_FRAME::ReCreateMenuBar()
// Save module in new lib // Save module in new lib
AddMenuItem( fileMenu, ID_MODEDIT_CREATE_NEW_LIB_AND_SAVE_CURRENT_PART, AddMenuItem( fileMenu, ID_MODEDIT_CREATE_NEW_LIB_AND_SAVE_CURRENT_PART,
_( "S&ave Module in a New Lib" ), _( "S&ave Module in a New Library" ),
_( "Create new library and save current module" ), _( "Create new library and save current module" ),
KiBitmap( new_library_xpm ) ); KiBitmap( new_library_xpm ) );
......
...@@ -85,6 +85,15 @@ public: ...@@ -85,6 +85,15 @@ public:
void ToolOnRightClick( wxCommandEvent& event ); void ToolOnRightClick( wxCommandEvent& event );
void OnSelectOptionToolbar( wxCommandEvent& event ); void OnSelectOptionToolbar( wxCommandEvent& event );
/**
* Function OnSaveLibraryAs
* saves the current library to a new name and/or library type.
*
* @note Saving as a new library type requires the plug-in to support saving libraris.
* @see PLUGIN::FootprintSave and PLUGIN::FootprintLibCreate
*/
void OnSaveLibraryAs( wxCommandEvent& aEvent );
/** /**
* Function OnHotKey * Function OnHotKey
* handle hot key events. * handle hot key events.
......
...@@ -67,6 +67,11 @@ BEGIN_EVENT_TABLE( FOOTPRINT_EDIT_FRAME, PCB_BASE_FRAME ) ...@@ -67,6 +67,11 @@ BEGIN_EVENT_TABLE( FOOTPRINT_EDIT_FRAME, PCB_BASE_FRAME )
EVT_COMBOBOX( ID_ON_GRID_SELECT, FOOTPRINT_EDIT_FRAME::OnSelectGrid ) EVT_COMBOBOX( ID_ON_GRID_SELECT, FOOTPRINT_EDIT_FRAME::OnSelectGrid )
EVT_TOOL( ID_MODEDIT_SELECT_CURRENT_LIB, FOOTPRINT_EDIT_FRAME::Process_Special_Functions ) EVT_TOOL( ID_MODEDIT_SELECT_CURRENT_LIB, FOOTPRINT_EDIT_FRAME::Process_Special_Functions )
#ifdef USE_PCBNEW_SEXPR_FOOTPRINT_LIBS
EVT_TOOL( ID_MODEDIT_SAVE_LIBRARY_AS, FOOTPRINT_EDIT_FRAME::OnSaveLibraryAs )
#endif
EVT_TOOL( ID_MODEDIT_SAVE_LIBMODULE, FOOTPRINT_EDIT_FRAME::Process_Special_Functions ) EVT_TOOL( ID_MODEDIT_SAVE_LIBMODULE, FOOTPRINT_EDIT_FRAME::Process_Special_Functions )
EVT_TOOL( ID_OPEN_MODULE_VIEWER, FOOTPRINT_EDIT_FRAME::Process_Special_Functions ) EVT_TOOL( ID_OPEN_MODULE_VIEWER, FOOTPRINT_EDIT_FRAME::Process_Special_Functions )
...@@ -109,9 +114,12 @@ BEGIN_EVENT_TABLE( FOOTPRINT_EDIT_FRAME, PCB_BASE_FRAME ) ...@@ -109,9 +114,12 @@ BEGIN_EVENT_TABLE( FOOTPRINT_EDIT_FRAME, PCB_BASE_FRAME )
FOOTPRINT_EDIT_FRAME::Process_Special_Functions ) FOOTPRINT_EDIT_FRAME::Process_Special_Functions )
EVT_MENU( ID_POPUP_MODEDIT_EDIT_BODY_ITEM, FOOTPRINT_EDIT_FRAME::Process_Special_Functions ) EVT_MENU( ID_POPUP_MODEDIT_EDIT_BODY_ITEM, FOOTPRINT_EDIT_FRAME::Process_Special_Functions )
EVT_MENU( ID_POPUP_MODEDIT_EDIT_WIDTH_ALL_EDGE, FOOTPRINT_EDIT_FRAME::Process_Special_Functions ) EVT_MENU( ID_POPUP_MODEDIT_EDIT_WIDTH_ALL_EDGE,
EVT_MENU( ID_POPUP_MODEDIT_EDIT_LAYER_CURRENT_EDGE, FOOTPRINT_EDIT_FRAME::Process_Special_Functions ) FOOTPRINT_EDIT_FRAME::Process_Special_Functions )
EVT_MENU( ID_POPUP_MODEDIT_EDIT_LAYER_ALL_EDGE, FOOTPRINT_EDIT_FRAME::Process_Special_Functions ) EVT_MENU( ID_POPUP_MODEDIT_EDIT_LAYER_CURRENT_EDGE,
FOOTPRINT_EDIT_FRAME::Process_Special_Functions )
EVT_MENU( ID_POPUP_MODEDIT_EDIT_LAYER_ALL_EDGE,
FOOTPRINT_EDIT_FRAME::Process_Special_Functions )
EVT_MENU( ID_POPUP_MODEDIT_ENTER_EDGE_WIDTH, FOOTPRINT_EDIT_FRAME::Process_Special_Functions ) EVT_MENU( ID_POPUP_MODEDIT_ENTER_EDGE_WIDTH, FOOTPRINT_EDIT_FRAME::Process_Special_Functions )
// Module transformations // Module transformations
...@@ -126,6 +134,7 @@ BEGIN_EVENT_TABLE( FOOTPRINT_EDIT_FRAME, PCB_BASE_FRAME ) ...@@ -126,6 +134,7 @@ BEGIN_EVENT_TABLE( FOOTPRINT_EDIT_FRAME, PCB_BASE_FRAME )
EVT_MENU( ID_MENU_PCB_SHOW_3D_FRAME, FOOTPRINT_EDIT_FRAME::Show3D_Frame ) EVT_MENU( ID_MENU_PCB_SHOW_3D_FRAME, FOOTPRINT_EDIT_FRAME::Show3D_Frame )
EVT_UPDATE_UI( ID_MODEDIT_DELETE_PART, FOOTPRINT_EDIT_FRAME::OnUpdateLibSelected ) EVT_UPDATE_UI( ID_MODEDIT_DELETE_PART, FOOTPRINT_EDIT_FRAME::OnUpdateLibSelected )
EVT_UPDATE_UI( ID_MODEDIT_SAVE_LIBRARY_AS, FOOTPRINT_EDIT_FRAME::OnUpdateLibSelected )
EVT_UPDATE_UI( ID_MODEDIT_EXPORT_PART, FOOTPRINT_EDIT_FRAME::OnUpdateModuleSelected ) EVT_UPDATE_UI( ID_MODEDIT_EXPORT_PART, FOOTPRINT_EDIT_FRAME::OnUpdateModuleSelected )
EVT_UPDATE_UI( ID_MODEDIT_CREATE_NEW_LIB_AND_SAVE_CURRENT_PART, EVT_UPDATE_UI( ID_MODEDIT_CREATE_NEW_LIB_AND_SAVE_CURRENT_PART,
FOOTPRINT_EDIT_FRAME::OnUpdateModuleSelected ) FOOTPRINT_EDIT_FRAME::OnUpdateModuleSelected )
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <trigo.h> #include <trigo.h>
#include <3d_struct.h> #include <3d_struct.h>
#include <class_title_block.h> #include <class_title_block.h>
#include <class_board.h> #include <class_board.h>
#include <class_dimension.h> #include <class_dimension.h>
#include <class_drawsegment.h> #include <class_drawsegment.h>
...@@ -43,9 +44,9 @@ ...@@ -43,9 +44,9 @@
#include <class_pad.h> #include <class_pad.h>
#include <class_track.h> #include <class_track.h>
#include <class_zone.h> #include <class_zone.h>
#include <kicad_plugin.h>
#include <pcb_plot_params.h> #include <pcb_plot_params.h>
#include <zones.h> #include <zones.h>
#include <pcb_parser.h> #include <pcb_parser.h>
using namespace std; using namespace std;
...@@ -318,6 +319,10 @@ BOARD_ITEM* PCB_PARSER::Parse() throw( IO_ERROR, PARSE_ERROR ) ...@@ -318,6 +319,10 @@ BOARD_ITEM* PCB_PARSER::Parse() throw( IO_ERROR, PARSE_ERROR )
item = (BOARD_ITEM*) parseBOARD(); item = (BOARD_ITEM*) parseBOARD();
break; break;
case T_module:
item = (BOARD_ITEM*) parseMODULE();
break;
default: default:
wxString err; wxString err;
err.Printf( _( "unknown token \"%s\"" ), GetChars( FromUTF8() ) ); err.Printf( _( "unknown token \"%s\"" ), GetChars( FromUTF8() ) );
......
...@@ -47,8 +47,10 @@ class TEXTE_MODULE; ...@@ -47,8 +47,10 @@ class TEXTE_MODULE;
class TEXTE_PCB; class TEXTE_PCB;
class MODULE; class MODULE;
class PCB_TARGET; class PCB_TARGET;
class PROPERTIES;
class S3D_MASTER; class S3D_MASTER;
class ZONE_CONTAINER; class ZONE_CONTAINER;
class FPL_CACHE;
WX_DECLARE_STRING_HASH_MAP( int, LAYER_HASH_MAP ); WX_DECLARE_STRING_HASH_MAP( int, LAYER_HASH_MAP );
......
...@@ -301,6 +301,7 @@ enum pcbnew_ids ...@@ -301,6 +301,7 @@ enum pcbnew_ids
ID_MODEDIT_CHECK, ID_MODEDIT_CHECK,
ID_MODEDIT_SELECT_CURRENT_LIB, ID_MODEDIT_SELECT_CURRENT_LIB,
ID_MODEDIT_SAVE_LIBMODULE, ID_MODEDIT_SAVE_LIBMODULE,
ID_MODEDIT_SAVE_LIBRARY_AS,
ID_MODEDIT_DELETE_PART, ID_MODEDIT_DELETE_PART,
ID_MODEDIT_NEW_MODULE, ID_MODEDIT_NEW_MODULE,
ID_MODEDIT_NEW_MODULE_FROM_WIZARD, ID_MODEDIT_NEW_MODULE_FROM_WIZARD,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment