Import system refactor for PCB plugins.

This commit is contained in:
Alex Shvartzkop 2023-08-13 05:26:06 +03:00
parent a0d96cea9f
commit 76e0d5981d
46 changed files with 956 additions and 974 deletions

View File

@ -341,63 +341,16 @@ wxString AllegroNetlistFileWildcard()
}
wxString LegacyPcbFileWildcard()
{
return _( "KiCad printed circuit board files" ) + AddFileExtListToFilter( { "brd" } );
}
wxString EaglePcbFileWildcard()
{
return _( "Eagle ver. 6.x XML PCB files" ) + AddFileExtListToFilter( { "brd" } );
}
wxString CadstarPcbArchiveFileWildcard()
{
return _( "CADSTAR PCB Archive files" ) + AddFileExtListToFilter( { "cpa" } );
}
wxString PCadPcbFileWildcard()
{
return _( "P-Cad 200x ASCII PCB files" ) + AddFileExtListToFilter( { "pcb" } );
}
wxString AltiumDesignerPcbFileWildcard()
{
return _( "Altium Designer PCB files" ) + AddFileExtListToFilter( { "PcbDoc" } );
}
wxString AltiumCircuitStudioPcbFileWildcard()
{
return _( "Altium Circuit Studio PCB files" ) + AddFileExtListToFilter( { "CSPcbDoc" } );
}
wxString AltiumCircuitMakerPcbFileWildcard()
{
return _( "Altium Circuit Maker PCB files" ) + AddFileExtListToFilter( { "CMPcbDoc" } );
}
wxString SolidworksPcbFileWildcard()
{
return _( "Solidworks PCB files" ) + AddFileExtListToFilter( { "SWPcbDoc" } );
}
wxString FabmasterPcbFileWildcard()
{
return _( "Fabmaster PCB files" ) + AddFileExtListToFilter( { "txt", "fab" } );
}
wxString PcbFileWildcard()
{
return _( "KiCad printed circuit board files" ) +
AddFileExtListToFilter( { KiCadPcbFileExtension } );
return _( "KiCad printed circuit board files" )
+ AddFileExtListToFilter( { KiCadPcbFileExtension } );
}
wxString KiCadFootprintLibFileWildcard()
{
return _( "KiCad footprint files" )
+ AddFileExtListToFilter( { KiCadFootprintFileExtension } );
return _( "KiCad footprint files" ) + AddFileExtListToFilter( { KiCadFootprintFileExtension } );
}
@ -408,30 +361,6 @@ wxString KiCadFootprintLibPathWildcard()
}
wxString LegacyFootprintLibPathWildcard()
{
return _( "Legacy footprint library files" ) + AddFileExtListToFilter( { "mod" } );
}
wxString AltiumFootprintLibPathWildcard()
{
return _( "Altium PCB footprint library files" ) + AddFileExtListToFilter( { "PcbLib" } );
}
wxString EagleFootprintLibPathWildcard()
{
return _( "Eagle ver. 6.x XML library files" ) + AddFileExtListToFilter( { "lbr" } );
}
wxString GedaPcbFootprintLibFileWildcard()
{
return _( "Geda PCB footprint library files" ) + AddFileExtListToFilter( { "fp" } );
}
wxString DrawingSheetFileWildcard()
{
return _( "Drawing sheet files" )

View File

@ -51,21 +51,23 @@ public:
/**
* A set of file types that the #SCH_IO_MGR knows about, and for which there
* has been a plugin written.
* has been a plugin written, in alphabetical order.
*/
// clang-format off
DEFINE_ENUM_VECTOR( SCH_FILE_T,
{
SCH_LEGACY, ///< Legacy Eeschema file formats prior to s-expression.
SCH_KICAD, ///< The s-expression version of the schematic.
SCH_ALTIUM, ///< Altium file format
SCH_CADSTAR_ARCHIVE, ///< CADSTAR Schematic Archive
SCH_EAGLE, ///< Autodesk Eagle file format
SCH_DATABASE, ///< KiCad database library
SCH_LTSPICE, /// LtSpice Schematic format
{
SCH_LEGACY, ///< Legacy Eeschema file formats prior to s-expression.
SCH_KICAD, ///< The s-expression version of the schematic.
SCH_ALTIUM, ///< Altium file format
SCH_CADSTAR_ARCHIVE, ///< CADSTAR Schematic Archive
SCH_DATABASE, ///< KiCad database library
SCH_EAGLE, ///< Autodesk Eagle file format
SCH_LTSPICE, ///< LtSpice Schematic format
// Add your schematic type here.
SCH_FILE_UNKNOWN
} )
// Add your schematic type here.
SCH_FILE_UNKNOWN
} )
// clang-format on
/**
* Return a #SCH_PLUGIN which the caller can use to import, export, save, or load

View File

@ -72,9 +72,10 @@ public:
~KIWAY_PLAYER() throw();
// For the aCtl argument of OpenProjectFiles()
#define KICTL_EAGLE_BRD (1<<0) ///< chosen *.brd file is Eagle according to user.
#define KICTL_CREATE (1<<1) ///< caller thinks requested project files may not exist.
#define KICTL_IMPORT_LIB (1<<2) ///< import all footprints into a project library.
#define KICTL_NONKICAD_ONLY (1<<0) ///< chosen file is non-KiCad according to user
#define KICTL_KICAD_ONLY (1<<1) ///< chosen file is from KiCad according to user
#define KICTL_CREATE (1<<2) ///< caller thinks requested project files may not exist.
#define KICTL_IMPORT_LIB (1<<3) ///< import all footprints into a project library.
/**
* Open a project or set of files given by @a aFileList.

View File

@ -218,22 +218,13 @@ extern wxString NetlistFileWildcard();
extern wxString AllegroNetlistFileWildcard();
extern wxString HtmlFileWildcard();
extern wxString CsvFileWildcard();
extern wxString LegacyPcbFileWildcard();
extern wxString PcbFileWildcard();
extern wxString EaglePcbFileWildcard();
extern wxString AltiumSchematicFileWildcard();
extern wxString CadstarSchematicArchiveFileWildcard();
extern wxString CadstarArchiveFilesWildcard();
extern wxString EagleSchematicFileWildcard();
extern wxString LtspiceSchematicFileWildcard();
extern wxString EagleFilesWildcard();
extern wxString PCadPcbFileWildcard();
extern wxString CadstarPcbArchiveFileWildcard();
extern wxString AltiumDesignerPcbFileWildcard();
extern wxString AltiumCircuitStudioPcbFileWildcard();
extern wxString AltiumCircuitMakerPcbFileWildcard();
extern wxString SolidworksPcbFileWildcard();
extern wxString FabmasterPcbFileWildcard();
extern wxString PdfFileWildcard();
extern wxString PSFileWildcard();
extern wxString MacrosFileWildcard();
@ -245,12 +236,8 @@ extern wxString FootprintPlaceFileWildcard();
extern wxString Shapes3DFileWildcard();
extern wxString IDF3DFileWildcard();
extern wxString DocModulesFileName();
extern wxString LegacyFootprintLibPathWildcard();
extern wxString KiCadFootprintLibFileWildcard();
extern wxString KiCadFootprintLibPathWildcard();
extern wxString AltiumFootprintLibPathWildcard();
extern wxString GedaPcbFootprintLibFileWildcard();
extern wxString EagleFootprintLibPathWildcard();
extern wxString TextFileWildcard();
extern wxString ModLegacyExportFileWildcard();
extern wxString ErcFileWildcard();

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 CERN
* Copyright (C) 2019-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2019-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@ -19,6 +19,7 @@
*/
#include "import_proj.h"
#include <kicad_manager_frame.h>
#include <kiway.h>
#include <kiway_player.h>
#include <wildcards_and_files_ext.h>
@ -28,120 +29,33 @@
#include <wx/msgdlg.h>
IMPORT_PROJ_HELPER::IMPORT_PROJ_HELPER( KICAD_MANAGER_FRAME* aFrame,
const wxString& aFile,
const wxString& aSchFileExtension,
const wxString& aPcbFileExtension ) :
IMPORT_PROJ_HELPER::IMPORT_PROJ_HELPER( KICAD_MANAGER_FRAME* aFrame,
const std::vector<wxString>& aSchFileExtensions,
const std::vector<wxString>& aPcbFileExtensions ) :
m_frame( aFrame ),
m_sch( aFile ), m_pcb( m_sch ), m_pro( m_sch )
m_schExtenstions( aSchFileExtensions ), m_pcbExtenstions( aPcbFileExtensions )
{
m_sch.SetExt( aSchFileExtension );
m_pcb.SetExt( aPcbFileExtension );
m_pro.SetExt( ProjectFileExtension );
}
const wxFileName& IMPORT_PROJ_HELPER::GetProj()
{
return m_pro;
}
wxString IMPORT_PROJ_HELPER::GetProjPath()
{
return m_pro.GetPath();
}
void IMPORT_PROJ_HELPER::SetProjPath( const wxString aPath )
{
m_pro.SetPath( aPath );
}
wxString IMPORT_PROJ_HELPER::GetProjFullPath()
{
return m_pro.GetFullPath();
}
wxString IMPORT_PROJ_HELPER::GetProjName()
{
return m_pro.GetName();
}
void IMPORT_PROJ_HELPER::CreateEmptyDirForProject()
void IMPORT_PROJ_HELPER::FindEmptyTargetDir()
{
// Append a new directory with the same name of the project file
// Keep iterating until we find an empty directory
wxString newDir = m_pro.GetName();
wxString newDir = m_TargetProj.GetName();
int attempt = 0;
m_pro.AppendDir( newDir );
m_TargetProj.AppendDir( newDir );
while( m_pro.DirExists() )
while( m_TargetProj.DirExists() )
{
m_pro.RemoveLastDir();
m_TargetProj.RemoveLastDir();
wxString suffix = wxString::Format( "_%d", ++attempt );
m_pro.AppendDir( newDir + suffix );
m_TargetProj.AppendDir( newDir + suffix );
}
}
void IMPORT_PROJ_HELPER::SetProjAbsolutePath()
{
m_pro.SetExt( ProjectFileExtension );
if( !m_pro.IsAbsolute() )
m_pro.MakeAbsolute();
}
bool IMPORT_PROJ_HELPER::CopyImportedFile( KICAD_T aFT, bool displayError )
{
wxASSERT( m_pro.GetExt() == ProjectFileExtension );
wxFileName fileCopy( m_pro );
wxFileName src, dest;
switch( aFT )
{
case SCHEMATIC_T: src = m_sch; break;
case PCB_T: src = m_pcb; break;
default: break;
}
fileCopy.SetExt( src.GetExt() );
if( src.Exists() && !fileCopy.SameAs( src ) )
{
if( !wxCopyFile( src.GetFullPath(), fileCopy.GetFullPath(), true ) )
{
if( displayError )
OutputCopyError( src, fileCopy );
return false;
}
}
switch( aFT )
{
case SCHEMATIC_T: m_shCopy = fileCopy; break;
case PCB_T: m_pcbCopy = fileCopy; break;
default: break;
}
return true;
}
bool IMPORT_PROJ_HELPER::CopyImportedFiles( bool displayError )
{
return CopyImportedFile( SCHEMATIC_T, displayError ) && CopyImportedFile( PCB_T, displayError );
}
void IMPORT_PROJ_HELPER::OutputCopyError( const wxFileName& aSrc, const wxFileName& aFileCopy )
{
wxString msg;
@ -155,53 +69,89 @@ void IMPORT_PROJ_HELPER::OutputCopyError( const wxFileName& aSrc, const wxFileNa
}
void IMPORT_PROJ_HELPER::AssociateFileWithProj( KICAD_T aFT, int aImportedFileType )
class SCOPED_FILE_REMOVER
{
wxFileName fileCopy, importedFile;
FRAME_T frame_type;
wxString m_file;
public:
SCOPED_FILE_REMOVER( const wxString& aFile ) : m_file( aFile ) {}
~SCOPED_FILE_REMOVER() { wxRemoveFile( m_file ); }
};
void IMPORT_PROJ_HELPER::ImportIndividualFile( KICAD_T aFT, int aImportedFileType )
{
FRAME_T frame_type;
wxString appImportFile;
std::vector<wxString> neededExts;
switch( aFT )
{
case SCHEMATIC_T:
importedFile = m_sch;
fileCopy = m_shCopy;
neededExts = m_schExtenstions;
frame_type = FRAME_SCH;
break;
case PCB_T:
importedFile = m_pcb;
fileCopy = m_pcbCopy;
neededExts = m_pcbExtenstions;
frame_type = FRAME_PCB_EDITOR;
break;
default: return;
}
if( fileCopy.FileExists() )
std::vector<SCOPED_FILE_REMOVER> copiedFiles;
for( wxString ext : neededExts )
{
KIWAY_PLAYER* frame = m_frame->Kiway().Player( frame_type, true );
if( ext == wxS( "INPUT" ) )
ext = m_InputFile.GetExt();
std::string packet =
StrPrintf( "%d\n%s", aImportedFileType, TO_UTF8( fileCopy.GetFullPath() ) );
frame->Kiway().ExpressMail( frame_type, MAIL_IMPORT_FILE, packet, m_frame );
wxFileName candidate = m_InputFile;
candidate.SetExt( ext );
if( !frame->IsShown() )
frame->Show( true );
if( !candidate.FileExists() )
continue;
// On Windows, Raise() does not bring the window on screen, when iconized
if( frame->IsIconized() )
frame->Iconize( false );
wxFileName targetFile( m_TargetProj.GetPath(), candidate.GetName(), candidate.GetExt() );
frame->Raise();
if( !targetFile.FileExists() )
{
bool copied = wxCopyFile( candidate.GetFullPath(), targetFile.GetFullPath(), false );
if( !fileCopy.SameAs( importedFile ) ) // Do not delete the original file!
wxRemoveFile( fileCopy.GetFullPath() );
if( copied )
{
// Will be auto-removed
copiedFiles.emplace_back( targetFile.GetFullPath() );
}
}
// Pick the first file to pass to application
if( appImportFile.empty() && targetFile.FileExists() )
appImportFile = targetFile.GetFullPath();
}
if( appImportFile.empty() )
return;
KIWAY_PLAYER* frame = m_frame->Kiway().Player( frame_type, true );
std::string packet = StrPrintf( "%d\n%s", aImportedFileType, TO_UTF8( appImportFile ) );
frame->Kiway().ExpressMail( frame_type, MAIL_IMPORT_FILE, packet, m_frame );
if( !frame->IsShown() )
frame->Show( true );
// On Windows, Raise() does not bring the window on screen, when iconized
if( frame->IsIconized() )
frame->Iconize( false );
frame->Raise();
}
void IMPORT_PROJ_HELPER::AssociateFilesWithProj( int aImportedSchFileType,
int aImportedPcbFileType )
void IMPORT_PROJ_HELPER::ImportFiles( int aImportedSchFileType, int aImportedPcbFileType )
{
AssociateFileWithProj( SCHEMATIC_T, aImportedSchFileType );
AssociateFileWithProj( PCB_T, aImportedPcbFileType );
ImportIndividualFile( SCHEMATIC_T, aImportedSchFileType );
ImportIndividualFile( PCB_T, aImportedPcbFileType );
}

View File

@ -1,37 +1,26 @@
#ifndef IMPORT_PROJ_H
#define IMPORT_PROJ_H
#include "kicad_manager_frame.h"
#include <wx/filename.h>
#include <core/typeinfo.h>
class KICAD_MANAGER_FRAME;
/**
* A helper class to import non Kicad project.
* */
class IMPORT_PROJ_HELPER
{
public:
IMPORT_PROJ_HELPER( KICAD_MANAGER_FRAME* aframe, const wxString& aFile,
const wxString& aSchFileExtension, const wxString& aPcbFileExtension );
const wxFileName& GetProj();
wxString GetProjPath();
void SetProjPath( const wxString aPath );
wxString GetProjFullPath();
wxString GetProjName();
IMPORT_PROJ_HELPER( KICAD_MANAGER_FRAME* aframe,
const std::vector<wxString>& aSchFileExtensions,
const std::vector<wxString>& aPcbFileExtensions );
/**
* @brief Appends a new directory with the name of the project file
* Keep iterating until an empty directory is found
*/
void CreateEmptyDirForProject();
void SetProjAbsolutePath();
/**
* @brief Copies project files to the destination directory
* @param displayError calls OutputCopyError() if true
*/
bool CopyImportedFiles( bool displayError = true );
void FindEmptyTargetDir();
/**
* @brief Converts imported files to kicad type files.
@ -39,18 +28,22 @@ public:
* @param aImportedSchFileType type of the imported schematic
* @param aImportedPcbFileType type of the imported PCB
*/
void AssociateFilesWithProj( int aImportedSchFileType, int aImportedPcbFileType );
void ImportFiles( int aImportedSchFileType, int aImportedPcbFileType );
wxFileName m_InputFile;
wxFileName m_TargetProj;
private:
KICAD_MANAGER_FRAME* m_frame;
wxFileName m_sch;
wxFileName m_shCopy;
wxFileName m_pcb;
wxFileName m_pcbCopy;
wxFileName m_pro;
bool CopyImportedFile( KICAD_T aKicad_T, bool displayError = true );
void OutputCopyError( const wxFileName& aSrc, const wxFileName& aFileCopy );
void AssociateFileWithProj( KICAD_T aKicad_T, int aImportedFileType );
std::vector<wxString> m_copiedSchPaths;
std::vector<wxString> m_copiedPcbPaths;
std::vector<wxString> m_schExtenstions;
std::vector<wxString> m_pcbExtenstions;
void OutputCopyError( const wxFileName& aSrc, const wxFileName& aFileCopy );
void ImportIndividualFile( KICAD_T aKicad_T, int aImportedFileType );
};
#endif

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2017-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2017-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* @author Russell Oliver <roliver8143@gmail.com>
*
@ -44,17 +44,17 @@
void KICAD_MANAGER_FRAME::ImportNonKiCadProject( const wxString& aWindowTitle,
const wxString& aFilesWildcard,
const wxString& aSchFileExtension,
const wxString& aPcbFileExtension,
const std::vector<std::string>& aSchFileExtensions,
const std::vector<std::string>& aPcbFileExtensions,
int aSchFileType, int aPcbFileType )
{
wxString msg;
wxString default_dir = GetMruPath();
int style = wxFD_OPEN | wxFD_FILE_MUST_EXIST;
int style = wxFD_OPEN | wxFD_FILE_MUST_EXIST;
wxFileDialog schdlg( this, aWindowTitle, default_dir, wxEmptyString, aFilesWildcard, style );
wxFileDialog inputdlg( this, aWindowTitle, default_dir, wxEmptyString, aFilesWildcard, style );
if( schdlg.ShowModal() == wxID_CANCEL )
if( inputdlg.ShowModal() == wxID_CANCEL )
return;
// OK, we got a new project to open. Time to close any existing project before we go on
@ -63,23 +63,29 @@ void KICAD_MANAGER_FRAME::ImportNonKiCadProject( const wxString& aWindowTitle,
if( !CloseProject( true ) )
return;
IMPORT_PROJ_HELPER importProj( this, schdlg.GetPath(), aSchFileExtension, aPcbFileExtension );
std::vector<wxString> schFileExts( aSchFileExtensions.begin(), aSchFileExtensions.end() );
std::vector<wxString> pcbFileExts( aPcbFileExtensions.begin(), aPcbFileExtensions.end() );
wxString protitle = _( "KiCad Project Destination" );
IMPORT_PROJ_HELPER importProj( this, schFileExts, pcbFileExts );
importProj.m_InputFile = inputdlg.GetPath();
// Don't use wxFileDialog here. On GTK builds, the default path is returned unless a
// file is actually selected.
wxDirDialog prodlg( this, protitle, importProj.GetProjPath(), wxDD_DEFAULT_STYLE );
wxDirDialog prodlg( this, _( "KiCad Project Destination" ), importProj.m_InputFile.GetPath(),
wxDD_DEFAULT_STYLE );
if( prodlg.ShowModal() == wxID_CANCEL )
return;
importProj.SetProjPath( prodlg.GetPath() );
wxString targetDir = prodlg.GetPath();
importProj.m_TargetProj.SetPath( targetDir );
importProj.m_TargetProj.SetName( importProj.m_InputFile.GetName() );
importProj.m_TargetProj.SetExt( ProjectFileExtension );
importProj.m_TargetProj.MakeAbsolute();
// Check if the project directory is empty
wxDir directory( importProj.GetProjPath() );
if( directory.HasFiles() )
if( wxDir( targetDir ).HasFiles() )
{
msg = _( "The selected directory is not empty. We recommend you "
"create projects in their own clean directory.\n\nDo you "
@ -92,9 +98,9 @@ void KICAD_MANAGER_FRAME::ImportNonKiCadProject( const wxString& aWindowTitle,
{
// Append a new directory with the same name of the project file
// Keep iterating until we find an empty directory
importProj.CreateEmptyDirForProject();
importProj.FindEmptyTargetDir();
if( !wxMkdir( importProj.GetProjPath() ) )
if( !wxMkdir( importProj.m_TargetProj.GetPath() ) )
{
msg = _( "Error creating new directory. Please try a different path. The "
"project cannot be imported." );
@ -106,17 +112,10 @@ void KICAD_MANAGER_FRAME::ImportNonKiCadProject( const wxString& aWindowTitle,
}
}
std::string packet;
CreateNewProject( importProj.m_TargetProj.GetFullPath(), false /* Don't create stub files */ );
LoadProject( importProj.m_TargetProj );
importProj.SetProjAbsolutePath();
if( !importProj.CopyImportedFiles() )
return;
CreateNewProject( importProj.GetProjFullPath(), false /* Don't create stub files */ );
LoadProject( importProj.GetProj() );
importProj.AssociateFilesWithProj( aSchFileType, aPcbFileType );
importProj.ImportFiles( aSchFileType, aPcbFileType );
ReCreateTreePrj();
m_active_project = true;
@ -126,14 +125,13 @@ void KICAD_MANAGER_FRAME::ImportNonKiCadProject( const wxString& aWindowTitle,
void KICAD_MANAGER_FRAME::OnImportCadstarArchiveFiles( wxCommandEvent& event )
{
ImportNonKiCadProject( _( "Import CADSTAR Archive Project Files" ),
CadstarArchiveFilesWildcard(), "csa", "cpa", SCH_IO_MGR::SCH_CADSTAR_ARCHIVE,
IO_MGR::CADSTAR_PCB_ARCHIVE );
CadstarArchiveFilesWildcard(), { "csa" }, { "cpa" },
SCH_IO_MGR::SCH_CADSTAR_ARCHIVE, IO_MGR::CADSTAR_PCB_ARCHIVE );
}
void KICAD_MANAGER_FRAME::OnImportEagleFiles( wxCommandEvent& event )
{
ImportNonKiCadProject( _( "Import Eagle Project Files" ), EagleFilesWildcard(),
LegacySchematicFileExtension, LegacyPcbFileExtension,
SCH_IO_MGR::SCH_EAGLE, IO_MGR::EAGLE );
}
ImportNonKiCadProject( _( "Import Eagle Project Files" ), EagleFilesWildcard(), { "sch" },
{ "brd" }, SCH_IO_MGR::SCH_EAGLE, IO_MGR::EAGLE );
}

View File

@ -232,16 +232,6 @@ KICAD_MANAGER_FRAME::KICAD_MANAGER_FRAME( wxWindow* parent, const wxString& titl
m_acceptedExts.emplace( GerberJobFileExtension, &KICAD_MANAGER_ACTIONS::viewDroppedGerbers );
m_acceptedExts.emplace( DrillFileExtension, &KICAD_MANAGER_ACTIONS::viewDroppedGerbers );
// Eagle files import
m_acceptedExts.emplace( EagleSchematicFileExtension,
&KICAD_MANAGER_ACTIONS::importNonKicadProj );
m_acceptedExts.emplace( EaglePcbFileExtension, &KICAD_MANAGER_ACTIONS::importNonKicadProj );
// Cadstar files import
m_acceptedExts.emplace( CadstarSchematicFileExtension,
&KICAD_MANAGER_ACTIONS::importNonKicadProj );
m_acceptedExts.emplace( CadstarPcbFileExtension, &KICAD_MANAGER_ACTIONS::importNonKicadProj );
DragAcceptFiles( true );
// Ensure the window is on top

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN (www.cern.ch)
* Copyright (C) 2019-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2019-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -77,15 +77,15 @@ public:
* @param aWindowTitle to display to the user when opening the files
* @param aFilesWildcard that includes both PCB and Schematic files (from
* wildcards_and_files_ext.h)
* @param aSchFileExtension e.g. "sch" or "csa"
* @param aPcbFileExtension e.g. "brd" or "cpa"
* @param aSchFileExtensions e.g. { "sch" } or { "csa" }. Specify { "INPUT" } to copy input file.
* @param aPcbFileExtensions e.g. { "brd" } or { "cpa" }. Specify { "INPUT" } to copy input file.
* @param aSchFileType Type of Schematic File to import (from SCH_IO_MGR::SCH_FILE_T)
* @param aPcbFileType Type of PCB File to import (from IO_MGR::PCB_FILE_T)
*/
void ImportNonKiCadProject( const wxString& aWindowTitle, const wxString& aFilesWildcard,
const wxString& aSchFileExtension,
const wxString& aPcbFileExtension, int aSchFileType,
int aPcbFileType );
const std::vector<std::string>& aSchFileExtensions,
const std::vector<std::string>& aPcbFileExtensions,
int aSchFileType, int aPcbFileType );
/**
* Open dialog to import CADSTAR Schematic and PCB Archive files.

View File

@ -83,11 +83,6 @@ TOOL_ACTION KICAD_MANAGER_ACTIONS::loadProject( TOOL_ACTION_ARGS()
.Scope( AS_GLOBAL )
.Parameter<wxString*>( nullptr ) ); // Default to no filename
TOOL_ACTION KICAD_MANAGER_ACTIONS::importNonKicadProj( TOOL_ACTION_ARGS()
.Name( "kicad.Control.importNonKicadProj" )
.Scope( AS_GLOBAL )
.Parameter<wxString*>( nullptr ) ); // Default to no filename
TOOL_ACTION KICAD_MANAGER_ACTIONS::viewDroppedGerbers( TOOL_ACTION_ARGS()
.Name( "kicad.Control.viewDroppedGerbers" )
.Scope( AS_GLOBAL )

View File

@ -37,7 +37,6 @@ public:
static TOOL_ACTION openProject;
static TOOL_ACTION closeProject;
static TOOL_ACTION loadProject;
static TOOL_ACTION importNonKicadProj;
static TOOL_ACTION viewDroppedGerbers;
static TOOL_ACTION editSchematic;

View File

@ -343,80 +343,6 @@ int KICAD_MANAGER_CONTROL::CloseProject( const TOOL_EVENT& aEvent )
}
int KICAD_MANAGER_CONTROL::ImportNonKicadProj( const TOOL_EVENT& aEvent )
{
if( !aEvent.Parameter<wxString*>() )
return -1;
wxFileName droppedFileName( *aEvent.Parameter<wxString*>() );
wxString schFileExtension, pcbFileExtension;
int schFileType, pcbFileType;
// Define extensions to use according to dropped file.
// Eagle project.
if( droppedFileName.GetExt() == EagleSchematicFileExtension
|| droppedFileName.GetExt() == EaglePcbFileExtension )
{
// Check if droppedFile is an eagle file.
// If not, return and do not import files.
if( !IsFileFromEDATool( droppedFileName, EDA_TOOLS::EAGLE ) )
return -1;
schFileExtension = EagleSchematicFileExtension;
pcbFileExtension = EaglePcbFileExtension;
schFileType = SCH_IO_MGR::SCH_EAGLE;
pcbFileType = IO_MGR::EAGLE;
}
// Cadstar project.
else if( droppedFileName.GetExt() == CadstarSchematicFileExtension
|| droppedFileName.GetExt() == CadstarPcbFileExtension )
{
schFileExtension = CadstarSchematicFileExtension;
pcbFileExtension = CadstarPcbFileExtension;
schFileType = SCH_IO_MGR::SCH_CADSTAR_ARCHIVE;
pcbFileType = IO_MGR::CADSTAR_PCB_ARCHIVE;
}
else
{
return -1;
}
IMPORT_PROJ_HELPER importProj( m_frame, droppedFileName.GetFullPath(), schFileExtension,
pcbFileExtension );
// Check if the project directory is empty
wxDir directory( importProj.GetProjPath() );
if( directory.HasFiles() )
{
// Append a new directory with the same name of the project file
// Keep iterating until we find an empty directory
importProj.CreateEmptyDirForProject();
if( !wxMkdir( importProj.GetProjPath() ) )
return -1;
}
importProj.SetProjAbsolutePath();
if( !importProj.CopyImportedFiles( false ) )
{
wxRmdir( importProj.GetProjPath() ); // Remove the previous created directory, before leaving.
return -1;
}
m_frame->CloseProject( true );
m_frame->CreateNewProject( importProj.GetProjFullPath(), false /* Don't create stub files */ );
m_frame->LoadProject( importProj.GetProj() );
importProj.AssociateFilesWithProj( schFileType, pcbFileType );
m_frame->ReCreateTreePrj();
m_frame->LoadProject( importProj.GetProj() );
return 0;
}
int KICAD_MANAGER_CONTROL::LoadProject( const TOOL_EVENT& aEvent )
{
if( aEvent.Parameter<wxString*>() )
@ -958,7 +884,6 @@ void KICAD_MANAGER_CONTROL::setTransitions()
Go( &KICAD_MANAGER_CONTROL::CloseProject, KICAD_MANAGER_ACTIONS::closeProject.MakeEvent() );
Go( &KICAD_MANAGER_CONTROL::SaveProjectAs, ACTIONS::saveAs.MakeEvent() );
Go( &KICAD_MANAGER_CONTROL::LoadProject, KICAD_MANAGER_ACTIONS::loadProject.MakeEvent() );
Go( &KICAD_MANAGER_CONTROL::ImportNonKicadProj, KICAD_MANAGER_ACTIONS::importNonKicadProj.MakeEvent() );
Go( &KICAD_MANAGER_CONTROL::ViewDroppedViewers, KICAD_MANAGER_ACTIONS::viewDroppedGerbers.MakeEvent() );
Go( &KICAD_MANAGER_CONTROL::Refresh, ACTIONS::zoomRedraw.MakeEvent() );

View File

@ -274,7 +274,7 @@ void DIALOG_BOARD_SETUP::onAuxiliaryAction( wxCommandEvent& aEvent )
{
WX_PROGRESS_REPORTER progressReporter( this, _( "Loading PCB" ), 1 );
otherBoard = pi->Load( boardFn.GetFullPath(), nullptr, nullptr, nullptr,
otherBoard = pi->LoadBoard( boardFn.GetFullPath(), nullptr, nullptr, nullptr,
&progressReporter );
if( importDlg.m_LayersOpt->GetValue() )

View File

@ -81,75 +81,6 @@ struct SUPPORTED_FILE_TYPE
IO_MGR::PCB_FILE_T m_Plugin;
};
/**
* Event IDs for the menu items in the split button menu for add a library
*/
enum {
ID_PANEL_FPLIB_ADD_KICADMOD = ID_PCBNEW_END_LIST,
ID_PANEL_FPLIB_ADD_ALTIUM,
ID_PANEL_FPLIB_ADD_CADSTAR,
ID_PANEL_FPLIB_ADD_EAGLE6,
ID_PANEL_FPLIB_ADD_KICADLEGACY,
ID_PANEL_FPLIB_ADD_GEDA,
};
/**
* Map with event id as the key to supported file types that will be listed for the add a
* library option.
*
*/
static const std::map<int, SUPPORTED_FILE_TYPE>& fileTypes()
{
/*
* TODO(C++20): Clean this up
* This is wrapped inside a function to prevent a static initialization order fiasco
* with the file extension variables. Once C++20 is allowed in KiCad code, those file
* extensions can be made constexpr and this can be removed from a function call and
* placed in the file normally.
*/
static const std::map<int, SUPPORTED_FILE_TYPE> fileTypes =
{
{ ID_PANEL_FPLIB_ADD_KICADMOD,
{
wxT( "KiCad (folder with .kicad_mod files)" ), wxT( "" ),
KiCadFootprintFileExtension, false, IO_MGR::KICAD_SEXP
}
},
{ ID_PANEL_FPLIB_ADD_ALTIUM,
{
"Altium (*.PcbLib)", AltiumFootprintLibPathWildcard(), "", true, IO_MGR::ALTIUM_DESIGNER
}
},
{ ID_PANEL_FPLIB_ADD_CADSTAR,
{
wxT( "CADSTAR (*.cpa)" ), CadstarPcbArchiveFileWildcard(), wxT( "" ),
true, IO_MGR::CADSTAR_PCB_ARCHIVE
}
},
{ ID_PANEL_FPLIB_ADD_EAGLE6,
{
wxT( "Eagle 6.x (*.lbr)" ), EagleFootprintLibPathWildcard(), wxT( "" ),
true, IO_MGR::EAGLE
}
},
{ ID_PANEL_FPLIB_ADD_KICADLEGACY,
{
wxT( "KiCad legacy (*.mod)" ), LegacyFootprintLibPathWildcard(), wxT( "" ),
true, IO_MGR::LEGACY
}
},
{ ID_PANEL_FPLIB_ADD_GEDA,
{
wxT( "Geda (folder with *.fp files)" ), wxT( "" ),
GedaPcbFootprintLibFileExtension, false, IO_MGR::GEDA_PCB
}
},
};
return fileTypes;
}
// clang-format on
/**
* Traverser implementation that looks to find any and all "folder" libraries by looking for files
@ -158,9 +89,8 @@ static const std::map<int, SUPPORTED_FILE_TYPE>& fileTypes()
class LIBRARY_TRAVERSER : public wxDirTraverser
{
public:
LIBRARY_TRAVERSER( wxString aSearchExtension, wxString aInitialDir )
: m_searchExtension( aSearchExtension ),
m_currentDir( aInitialDir )
LIBRARY_TRAVERSER( std::vector<std::string> aSearchExtensions, wxString aInitialDir ) :
m_searchExtensions( aSearchExtensions ), m_currentDir( aInitialDir )
{
}
@ -168,8 +98,11 @@ public:
{
wxFileName file( aFileName );
if( m_searchExtension.IsSameAs( file.GetExt(), false ) )
m_foundDirs.insert( { m_currentDir, 1 } );
for( const std::string& ext : m_searchExtensions )
{
if( file.GetExt().IsSameAs( ext, false ) )
m_foundDirs.insert( { m_currentDir, 1 } );
}
return wxDIR_CONTINUE;
}
@ -204,7 +137,7 @@ public:
}
private:
wxString m_searchExtension;
std::vector<std::string> m_searchExtensions;
wxString m_currentDir;
std::unordered_map<wxString, int> m_foundDirs;
std::unordered_map<wxString, int> m_failedDirs;
@ -354,18 +287,14 @@ PANEL_FP_LIB_TABLE::PANEL_FP_LIB_TABLE( DIALOG_EDIT_LIBRARY_TABLES* aParent,
// add Cut, Copy, and Paste to wxGrids
m_path_subs_grid->PushEventHandler( new GRID_TRICKS( m_path_subs_grid ) );
populatePluginList();
wxArrayString choices;
choices.Add( IO_MGR::ShowType( IO_MGR::KICAD_SEXP ) );
choices.Add( IO_MGR::ShowType( IO_MGR::LEGACY ) );
choices.Add( IO_MGR::ShowType( IO_MGR::ALTIUM_DESIGNER ) );
choices.Add( IO_MGR::ShowType( IO_MGR::CADSTAR_PCB_ARCHIVE ) );
choices.Add( IO_MGR::ShowType( IO_MGR::EAGLE ) );
choices.Add( IO_MGR::ShowType( IO_MGR::GEDA_PCB ) );
for( auto& [fileType, desc] : m_supportedFpFiles )
choices.Add( IO_MGR::ShowType( fileType ) );
/* PCAD_PLUGIN does not support Footprint*() functions
choices.Add( IO_MGR::ShowType( IO_MGR::PCAD ) );
*/
PCBNEW_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>();
if( cfg->m_lastFootprintLibDir.IsEmpty() )
@ -473,12 +402,40 @@ PANEL_FP_LIB_TABLE::PANEL_FP_LIB_TABLE( DIALOG_EDIT_LIBRARY_TABLES* aParent,
// Populate the browse library options
wxMenu* browseMenu = m_browseButton->GetSplitButtonMenu();
for( const std::pair<const int, SUPPORTED_FILE_TYPE>& fileType : fileTypes() )
auto joinExts = []( const std::vector<std::string>& aExts )
{
browseMenu->Append( fileType.first, fileType.second.m_Description );
wxString joined;
for( const std::string& ext : aExts )
{
if( !joined.empty() )
joined << wxS( ", " );
joined << wxS( "*." ) << ext;
}
return joined;
};
for( auto& [type, desc] : m_supportedFpFiles )
{
wxString entryStr = IO_MGR::ShowType( type );
if( desc.m_IsFile && !desc.m_FileExtensions.empty() )
{
entryStr << wxString::Format( wxS( " (%s)" ), joinExts( desc.m_FileExtensions ) );
}
else if( !desc.m_IsFile && !desc.m_ExtensionsInDir.empty() )
{
wxString midPart =
wxString::Format( _( "folder with %s files" ), joinExts( desc.m_ExtensionsInDir ) );
entryStr << wxString::Format( wxS( " (%s)" ), midPart );
}
browseMenu->Append( type, entryStr );
browseMenu->Bind( wxEVT_COMMAND_MENU_SELECTED, &PANEL_FP_LIB_TABLE::browseLibrariesHandler,
this, fileType.first );
this, type );
}
Layout();
@ -501,6 +458,21 @@ PANEL_FP_LIB_TABLE::~PANEL_FP_LIB_TABLE()
}
void PANEL_FP_LIB_TABLE::populatePluginList()
{
for( const auto& plugin : IO_MGR::PLUGIN_REGISTRY::Instance()->AllPlugins() )
{
PLUGIN::RELEASER pi( plugin.m_createFunc() );
if( !pi )
continue;
if( PLUGIN_FILE_DESC desc = pi->GetFootprintLibDesc() )
m_supportedFpFiles.emplace( plugin.m_type, desc );
}
}
bool PANEL_FP_LIB_TABLE::verifyTables()
{
wxString msg;
@ -766,45 +738,41 @@ void PANEL_FP_LIB_TABLE::browseLibrariesHandler( wxCommandEvent& event )
if( !m_cur_grid->CommitPendingChanges() )
return;
std::map<int, SUPPORTED_FILE_TYPE>::const_iterator fileTypeIt;
IO_MGR::PCB_FILE_T fileType = IO_MGR::FILE_TYPE_NONE;
// We are bound both to the menu and button with this one handler
// So we must set the file type based on it
if( event.GetEventType() == wxEVT_BUTTON )
{
// Let's default to adding a kicad footprint file for just the footprint
fileTypeIt = fileTypes().find( ID_PANEL_FPLIB_ADD_KICADMOD );
fileType = IO_MGR::KICAD_SEXP;
}
else
{
fileTypeIt = fileTypes().find( event.GetId() );
fileType = static_cast<IO_MGR::PCB_FILE_T>( event.GetId() );
}
if( fileTypeIt == fileTypes().end() )
if( fileType == IO_MGR::FILE_TYPE_NONE )
{
wxLogWarning( wxT( "File type selection event received but could not find the file type "
"in the table" ) );
return;
}
SUPPORTED_FILE_TYPE fileType = fileTypeIt->second;
PCBNEW_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>();
wxArrayString files;
wxString title;
title.Printf( _( "Select %s Library" ), fileType.m_Description );
const PLUGIN_FILE_DESC& fileDesc = m_supportedFpFiles.at( fileType );
PCBNEW_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>();
wxString title = wxString::Format( _( "Select %s Library" ), IO_MGR::ShowType( fileType ) );
wxString openDir = cfg->m_lastFootprintLibDir;
if( m_cur_grid == m_project_grid )
openDir = m_lastProjectLibDir;
if( fileType.m_IsFile )
wxArrayString files;
if( fileDesc.m_IsFile )
{
wxFileDialog dlg( this, title, openDir, wxEmptyString, fileType.m_FileFilter,
wxFileDialog dlg( this, title, openDir, wxEmptyString, fileDesc.FileFilter(),
wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE );
int result = dlg.ShowModal();
@ -840,11 +808,11 @@ void PANEL_FP_LIB_TABLE::browseLibrariesHandler( wxCommandEvent& event )
return;
// is there a file extension configured to hunt out their containing folders?
if( fileType.m_FolderSearchExtension != "" )
if( !fileDesc.m_ExtensionsInDir.empty() )
{
wxDir rootDir( dlg.GetPath() );
LIBRARY_TRAVERSER traverser( fileType.m_FolderSearchExtension, rootDir.GetName() );
LIBRARY_TRAVERSER traverser( fileDesc.m_ExtensionsInDir, rootDir.GetName() );
rootDir.Traverse( traverser );
traverser.GetPaths( files );
@ -897,7 +865,7 @@ void PANEL_FP_LIB_TABLE::browseLibrariesHandler( wxCommandEvent& event )
wxString nickname = LIB_ID::FixIllegalChars( fn.GetName(), true );
bool doAdd = true;
if( fileType.m_Plugin == IO_MGR::KICAD_SEXP && fn.GetExt() != KiCadFootprintLibPathExtension )
if( fileType == IO_MGR::KICAD_SEXP && fn.GetExt() != KiCadFootprintLibPathExtension )
nickname = LIB_ID::FixIllegalChars( fn.GetFullName(), true );
if( cur_model()->ContainsNickname( nickname ) )
@ -919,7 +887,7 @@ void PANEL_FP_LIB_TABLE::browseLibrariesHandler( wxCommandEvent& event )
m_cur_grid->SetCellValue( last_row, COL_NICKNAME, nickname );
m_cur_grid->SetCellValue( last_row, COL_TYPE, IO_MGR::ShowType( fileType.m_Plugin ) );
m_cur_grid->SetCellValue( last_row, COL_TYPE, IO_MGR::ShowType( fileType ) );
// try to use path normalized to an environmental variable or project path
wxString path = NormalizePath( filePath, &envVars, m_projectBasePath );

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2018-2020 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2018-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@ -22,6 +22,7 @@
#include <panel_fp_lib_table_base.h>
#include <widgets/wx_grid.h>
#include <io_mgr.h>
class FP_LIB_TABLE;
class FP_LIB_TABLE_GRID;
@ -63,6 +64,7 @@ private:
/// Populate the readonly environment variable table with names and values
/// by examining all the full_uri columns.
void populateEnvironReadOnlyTable();
void populatePluginList();
FP_LIB_TABLE_GRID* global_model() const
{
@ -91,6 +93,8 @@ private:
//< Transient (unsaved) last browsed folder when adding a project level library.
wxString m_lastProjectLibDir;
std::map<IO_MGR::PCB_FILE_T, PLUGIN_FILE_DESC> m_supportedFpFiles;
};
#endif // PANEL_FP_LIB_TABLE_H

View File

@ -88,99 +88,68 @@
* @param aKicadFilesOnly true to list KiCad pcb files plugins only, false to list import plugins.
* @return true if chosen, else false if user aborted.
*/
bool AskLoadBoardFileName( PCB_EDIT_FRAME* aParent, int* aCtl, wxString* aFileName,
bool aKicadFilesOnly )
bool AskLoadBoardFileName( PCB_EDIT_FRAME* aParent, wxString* aFileName, int aCtl = 0 )
{
// This is a subset of all PLUGINs which are trusted to be able to
// load a BOARD. User may occasionally use the wrong plugin to load a
// *.brd file (since both legacy and eagle use *.brd extension),
// but eventually *.kicad_pcb will be more common than legacy *.brd files.
std::vector<PLUGIN_FILE_DESC> descriptions;
// clang-format off
static const struct
for( const auto& plugin : IO_MGR::PLUGIN_REGISTRY::Instance()->AllPlugins() )
{
const wxString& filter;
IO_MGR::PCB_FILE_T pluginType;
} loaders[] =
bool isKiCad = plugin.m_type == IO_MGR::KICAD_SEXP || plugin.m_type == IO_MGR::LEGACY;
if( ( aCtl & KICTL_KICAD_ONLY ) && !isKiCad )
continue;
if( ( aCtl & KICTL_NONKICAD_ONLY ) && isKiCad )
continue;
// release the PLUGIN even if an exception is thrown.
PLUGIN::RELEASER pi( plugin.m_createFunc() );
wxCHECK( pi, false );
const PLUGIN_FILE_DESC& desc = pi->GetBoardFileDesc();
if( desc.m_FileExtensions.empty() )
continue;
descriptions.emplace_back( desc );
}
wxString fileFiltersStr;
std::vector<std::string> allExtensions;
std::set<wxString> allWildcardsSet;
for( const PLUGIN_FILE_DESC desc : descriptions )
{
// Current Kicad board files.
{ PcbFileWildcard(), IO_MGR::KICAD_SEXP },
if( !fileFiltersStr.IsEmpty() )
fileFiltersStr += wxChar( '|' );
// Old Kicad board files.
{ LegacyPcbFileWildcard(), IO_MGR::LEGACY },
fileFiltersStr += desc.FileFilter();
// Import Altium Circuit Maker board files.
{ AltiumCircuitMakerPcbFileWildcard(), IO_MGR::ALTIUM_CIRCUIT_MAKER },
// Import Altium Circuit Studio board files.
{ AltiumCircuitStudioPcbFileWildcard(), IO_MGR::ALTIUM_CIRCUIT_STUDIO },
// Import Altium Designer board files.
{ AltiumDesignerPcbFileWildcard(), IO_MGR::ALTIUM_DESIGNER },
// Import Solidworks PCB (based on Altium) board files.
{ SolidworksPcbFileWildcard(), IO_MGR::SOLIDWORKS_PCB },
// Import Cadstar PCB Archive board files.
{ CadstarPcbArchiveFileWildcard(), IO_MGR::CADSTAR_PCB_ARCHIVE },
// Import Eagle board files.
{ EaglePcbFileWildcard(), IO_MGR::EAGLE },
// Import PCAD board files.
{ PCadPcbFileWildcard(), IO_MGR::PCAD },
// Import Fabmaster board files.
{ FabmasterPcbFileWildcard(), IO_MGR::FABMASTER },
};
// clang-format on
wxFileName fileName( *aFileName );
wxString fileFilters;
if( aKicadFilesOnly )
{
std::vector<std::string> fileExtensions;
for( unsigned ii = 0; ii < 2; ++ii )
for( const std::string& ext : desc.m_FileExtensions )
{
if( !fileFilters.IsEmpty() )
fileFilters += wxChar( '|' );
fileFilters += wxGetTranslation( loaders[ii].filter );
PLUGIN::RELEASER plugin( IO_MGR::PluginFind( loaders[ii].pluginType ) );
wxCHECK( plugin, false );
fileExtensions.push_back( plugin->GetFileExtension().ToStdString() );
allExtensions.emplace_back( ext );
allWildcardsSet.insert( wxT( "*." ) + formatWildcardExt( ext ) + wxT( ";" ) );
}
}
fileFilters = _( "All KiCad Board Files" ) + AddFileExtListToFilter( fileExtensions )
+ wxT( "|" ) + fileFilters;
wxString allWildcardsStr;
for( const wxString& wildcard : allWildcardsSet )
allWildcardsStr << wildcard;
if( aCtl & KICTL_KICAD_ONLY )
{
fileFiltersStr = _( "All KiCad Board Files" ) + AddFileExtListToFilter( allExtensions )
+ wxT( "|" ) + allWildcardsStr;
}
else
{
wxString allWildcards;
for( unsigned ii = 2; ii < arrayDim( loaders ); ++ii )
{
if( !fileFilters.IsEmpty() )
fileFilters += wxChar( '|' );
fileFilters += wxGetTranslation( loaders[ii].filter );
PLUGIN::RELEASER plugin( IO_MGR::PluginFind( loaders[ii].pluginType ) );
wxCHECK( plugin, false );
allWildcards += wxT( "*." ) + formatWildcardExt( plugin->GetFileExtension() ) +
wxT( ";" );
}
fileFilters = _( "All supported formats" ) + wxT( "|" ) + allWildcards + wxT( "|" ) +
fileFilters;
fileFiltersStr = _( "All supported formats" ) + wxT( "|" ) + allWildcardsStr + wxT( "|" )
+ fileFiltersStr;
}
wxString path;
wxString name;
wxFileName fileName( *aFileName );
wxString path;
wxString name;
if( fileName.FileExists() )
{
@ -197,15 +166,12 @@ bool AskLoadBoardFileName( PCB_EDIT_FRAME* aParent, int* aCtl, wxString* aFileNa
}
wxFileDialog dlg( aParent,
aKicadFilesOnly ? _( "Open Board File" ) : _( "Import Non KiCad Board File" ),
path, name, fileFilters, wxFD_OPEN | wxFD_FILE_MUST_EXIST );
( aCtl & KICTL_KICAD_ONLY ) ? _( "Open Board File" )
: _( "Import Non KiCad Board File" ),
path, name, fileFiltersStr, wxFD_OPEN | wxFD_FILE_MUST_EXIST );
if( dlg.ShowModal() == wxID_OK )
{
// For import option, if Eagle (*.brd files), tell OpenProjectFiles() to use Eagle plugin.
// It's the only special case because of the duplicate use of the *.brd file extension.
// Other cases are clear because of unique file extensions.
*aCtl = aKicadFilesOnly ? 0 : KICTL_EAGLE_BRD;
*aFileName = dlg.GetPath();
aParent->SetMruPath( wxFileName( dlg.GetPath() ).GetPath() );
return true;
@ -276,15 +242,13 @@ void PCB_EDIT_FRAME::OnFileHistory( wxCommandEvent& event )
if( !!fn )
{
int open_ctl = 0;
if( !wxFileName::IsFileReadable( fn ) )
{
if( !AskLoadBoardFileName( this, &open_ctl, &fn, true ) )
if( !AskLoadBoardFileName( this, &fn, KICTL_KICAD_ONLY ) )
return;
}
OpenProjectFiles( std::vector<wxString>( 1, fn ), open_ctl );
OpenProjectFiles( std::vector<wxString>( 1, fn ), KICTL_KICAD_ONLY );
}
}
@ -310,20 +274,20 @@ bool PCB_EDIT_FRAME::Files_io_from_id( int id )
{
case ID_LOAD_FILE:
{
int open_ctl = 0;
wxString fileName = Prj().AbsolutePath( GetBoard()->GetFileName() );
int open_ctl = KICTL_KICAD_ONLY;
wxString fileName = Prj().AbsolutePath( GetBoard()->GetFileName() );
return AskLoadBoardFileName( this, &open_ctl, &fileName, true )
&& OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
return AskLoadBoardFileName( this, &fileName, open_ctl )
&& OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
}
case ID_IMPORT_NON_KICAD_BOARD:
{
int open_ctl = 1;
wxString fileName; // = Prj().AbsolutePath( GetBoard()->GetFileName() );
int open_ctl = KICTL_NONKICAD_ONLY;
wxString fileName; // = Prj().AbsolutePath( GetBoard()->GetFileName() );
return AskLoadBoardFileName( this, &open_ctl, &fileName, false )
&& OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
return AskLoadBoardFileName( this, &fileName, open_ctl )
&& OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
}
case ID_MENU_RECOVER_BOARD_AUTOSAVE:
@ -481,65 +445,28 @@ bool PCB_EDIT_FRAME::Files_io_from_id( int id )
// The KIWAY_PLAYER::OpenProjectFiles() API knows nothing about plugins, so
// determine how to load the BOARD here, with minor assistance from KICTL_EAGLE_BRD
// bit flag.
IO_MGR::PCB_FILE_T plugin_type( const wxString& aFileName, int aCtl )
// determine how to load the BOARD here
IO_MGR::PCB_FILE_T FindBoardPlugin( const wxString& aFileName, int aCtl = 0 )
{
IO_MGR::PCB_FILE_T pluginType;
const auto& plugins = IO_MGR::PLUGIN_REGISTRY::Instance()->AllPlugins();
wxFileName fn = aFileName;
for( const auto& plugin : plugins )
{
bool isKiCad = plugin.m_type == IO_MGR::KICAD_SEXP || plugin.m_type == IO_MGR::LEGACY;
// Note: file extensions are expected to be in lower case.
// This is not always true, especially when importing files, so the string
// comparisons are case insensitive to try to find the suitable plugin.
if( ( aCtl & KICTL_KICAD_ONLY ) && !isKiCad )
continue;
if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::LEGACY ) ) == 0 )
{
wxFileInputStream input( aFileName );
bool is_legacy = true;
if( ( aCtl & KICTL_NONKICAD_ONLY ) && isKiCad )
continue;
if(input.IsOk() && !input.Eof() )
{
wxTextInputStream text( input );
wxString line = text.ReadLine();
PLUGIN::RELEASER pi( plugin.m_createFunc() );
if( !line.StartsWith( wxT( "PCBNEW" ) ) )
is_legacy = false;
}
// both legacy and eagle share a common file extension.
pluginType = ( aCtl & KICTL_EAGLE_BRD ) || !is_legacy ? IO_MGR::EAGLE : IO_MGR::LEGACY;
}
else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::PCAD ) ) == 0 )
{
pluginType = IO_MGR::PCAD;
}
else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::ALTIUM_DESIGNER ) ) == 0 )
{
pluginType = IO_MGR::ALTIUM_DESIGNER;
}
else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::ALTIUM_CIRCUIT_STUDIO ) ) == 0 )
{
pluginType = IO_MGR::ALTIUM_CIRCUIT_STUDIO;
}
else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::ALTIUM_CIRCUIT_MAKER ) ) == 0 )
{
pluginType = IO_MGR::ALTIUM_CIRCUIT_MAKER;
}
else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::CADSTAR_PCB_ARCHIVE ) ) == 0 )
{
pluginType = IO_MGR::CADSTAR_PCB_ARCHIVE;
}
else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::FABMASTER ) ) == 0 )
{
pluginType = IO_MGR::FABMASTER;
}
else
{
pluginType = IO_MGR::KICAD_SEXP;
if( pi->CanReadBoard( aFileName ) )
return plugin.m_type;
}
return pluginType;
return IO_MGR::FILE_TYPE_NONE;
}
@ -665,7 +592,7 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
// No save prompt (we already prompted above), and only reset to a new blank board if new
Clear_Pcb( false, !is_new );
IO_MGR::PCB_FILE_T pluginType = plugin_type( fullFileName, aCtl );
IO_MGR::PCB_FILE_T pluginType = FindBoardPlugin( fullFileName, aCtl );
bool converted = pluginType != IO_MGR::LEGACY && pluginType != IO_MGR::KICAD_SEXP;
@ -1285,10 +1212,9 @@ bool PCB_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType )
case IO_MGR::CADSTAR_PCB_ARCHIVE:
case IO_MGR::EAGLE:
return OpenProjectFiles( std::vector<wxString>( 1, aFileName ),
KICTL_EAGLE_BRD | KICTL_IMPORT_LIB );
KICTL_NONKICAD_ONLY | KICTL_IMPORT_LIB );
default:
break;
default: break;
}
return false;

View File

@ -70,176 +70,66 @@ static const wxString INFO_LEGACY_LIB_WARN_DELETE(
"before deleting a footprint" ) );
/**
* Prompt the user for a footprint file to open.
* @param aParent - parent window for the dialog
* @param aLastPath - last opened path
*/
static wxFileName getFootprintFilenameFromUser( wxWindow* aParent, const wxString& aLastPath )
{
static int lastFilterIndex = 0; // To store the last choice during a session.
wxString wildCard;
wildCard << KiCadFootprintLibFileWildcard() << wxChar( '|' )
<< ModLegacyExportFileWildcard() << wxChar( '|' )
<< GedaPcbFootprintLibFileWildcard() << wxChar( '|' )
<< AllFilesWildcard();
wxFileDialog dlg( aParent, _( "Import Footprint" ), aLastPath, wxEmptyString, wildCard,
wxFD_OPEN | wxFD_FILE_MUST_EXIST );
dlg.SetFilterIndex( lastFilterIndex );
if( dlg.ShowModal() == wxID_CANCEL )
return wxFileName();
lastFilterIndex = dlg.GetFilterIndex();
return wxFileName( dlg.GetPath() );
}
/**
* Read a file to detect the type.
* @param aFile - open file to be read. File pointer will be closed.
* @param aFileName - file name to be read
* @param aName - wxString to receive the footprint name if type is LEGACY
*/
static IO_MGR::PCB_FILE_T detect_file_type( FILE* aFile, const wxFileName& aFileName,
wxString* aName )
{
FILE_LINE_READER freader( aFile, aFileName.GetFullPath() );
WHITESPACE_FILTER_READER reader( freader );
IO_MGR::PCB_FILE_T file_type;
wxASSERT( aName );
reader.ReadLine();
char* line = reader.Line();
if( !line )
{
return IO_MGR::FILE_TYPE_NONE;
}
// first .kicad_mod file versions starts by "(module"
// recent .kicad_mod file versions starts by "(footprint"
if( strncasecmp( line, "(module", strlen( "(module" ) ) == 0
|| strncasecmp( line, "(footprint", strlen( "(footprint" ) ) == 0 )
{
file_type = IO_MGR::KICAD_SEXP;
*aName = aFileName.GetName();
}
else if( !strncasecmp( line, FOOTPRINT_LIBRARY_HEADER, FOOTPRINT_LIBRARY_HEADER_CNT ) )
{
file_type = IO_MGR::LEGACY;
while( reader.ReadLine() )
{
if( !strncasecmp( line, "$MODULE", strlen( "$MODULE" ) ) )
{
*aName = FROM_UTF8( StrPurge( line + strlen( "$MODULE" ) ) );
break;
}
}
}
else if( !strncasecmp( line, "Element", strlen( "Element" ) ) )
{
file_type = IO_MGR::GEDA_PCB;
*aName = aFileName.GetName();
}
else
{
file_type = IO_MGR::FILE_TYPE_NONE;
}
return file_type;
}
/**
* Parse a footprint using a PLUGIN.
* @param aFileName - file name to parse
* @param aFileType - type of the file
* @param aName - name of the footprint
*/
static FOOTPRINT* parse_footprint_with_plugin( const wxFileName& aFileName,
IO_MGR::PCB_FILE_T aFileType,
const wxString& aName )
{
wxString path;
switch( aFileType )
{
case IO_MGR::GEDA_PCB: path = aFileName.GetPath(); break;
case IO_MGR::LEGACY: path = aFileName.GetFullPath(); break;
default: wxFAIL_MSG( wxT( "unexpected IO_MGR::PCB_FILE_T" ) ); break;
}
PLUGIN::RELEASER pi( IO_MGR::PluginFind( aFileType ) );
return pi->FootprintLoad( path, aName );
}
/**
* Parse a KICAD footprint.
* @param aFileName - file name to parse
*/
static FOOTPRINT* parse_footprint_kicad( const wxFileName& aFileName )
{
wxString fcontents;
PCB_PLUGIN pcb_io;
wxFFile f( aFileName.GetFullPath() );
if( !f.IsOpened() )
return nullptr;
f.ReadAll( &fcontents );
return dynamic_cast<FOOTPRINT*>( pcb_io.Parse( fcontents ) );
}
/**
* Try to load a footprint, returning nullptr if the file couldn't be accessed.
* @param aFileName - file name to load
* @param aFileType - type of the file to load
* @param aName - footprint name
*/
FOOTPRINT* try_load_footprint( const wxFileName& aFileName, IO_MGR::PCB_FILE_T aFileType,
const wxString& aName )
{
FOOTPRINT* footprint;
switch( aFileType )
{
case IO_MGR::GEDA_PCB:
case IO_MGR::LEGACY:
footprint = parse_footprint_with_plugin( aFileName, aFileType, aName );
break;
case IO_MGR::KICAD_SEXP:
footprint = parse_footprint_kicad( aFileName );
break;
default:
wxFAIL_MSG( wxT( "unexpected IO_MGR::PCB_FILE_T" ) );
footprint = nullptr;
}
return footprint;
}
FOOTPRINT* FOOTPRINT_EDIT_FRAME::ImportFootprint( const wxString& aName )
{
wxFileName fn;
if( aName != wxT("") )
if( !aName.empty() )
{
fn = aName;
}
else
fn = getFootprintFilenameFromUser( this, m_mruPath );
{
// Prompt the user for a footprint file to open.
static int lastFilterIndex = 0; // To store the last choice during a session.
wxString fileFiltersStr;
std::vector<std::string> allExtensions;
std::set<wxString> allWildcardsSet;
//for( const PLUGIN_FILE_DESC desc : descriptions )
for( const auto& plugin : IO_MGR::PLUGIN_REGISTRY::Instance()->AllPlugins() )
{
PLUGIN::RELEASER pi( plugin.m_createFunc() );
if( !pi )
continue;
PLUGIN_FILE_DESC desc = pi->GetFootprintFileDesc();
if( !desc )
continue;
if( !fileFiltersStr.IsEmpty() )
fileFiltersStr += wxChar( '|' );
fileFiltersStr += desc.FileFilter();
for( const std::string& ext : desc.m_FileExtensions )
{
allExtensions.emplace_back( ext );
allWildcardsSet.insert( wxT( "*." ) + formatWildcardExt( ext ) + wxT( ";" ) );
}
}
wxString allWildcardsStr;
for( const wxString& wildcard : allWildcardsSet )
allWildcardsStr << wildcard;
fileFiltersStr = _( "All supported formats" ) + wxT( "|" ) + allWildcardsStr + wxT( "|" )
+ fileFiltersStr;
wxFileDialog dlg( this, _( "Import Footprint" ), m_mruPath, wxEmptyString, fileFiltersStr,
wxFD_OPEN | wxFD_FILE_MUST_EXIST );
dlg.SetFilterIndex( lastFilterIndex );
if( dlg.ShowModal() == wxID_CANCEL )
return nullptr;
lastFilterIndex = dlg.GetFilterIndex();
fn = dlg.GetPath();
}
if( !fn.IsOk() )
return nullptr;
@ -255,8 +145,24 @@ FOOTPRINT* FOOTPRINT_EDIT_FRAME::ImportFootprint( const wxString& aName )
m_mruPath = fn.GetPath();
wxString footprintName;
IO_MGR::PCB_FILE_T fileType = detect_file_type( fp, fn.GetFullPath(), &footprintName );
IO_MGR::PCB_FILE_T fileType = IO_MGR::FILE_TYPE_NONE;
for( const auto& plugin : IO_MGR::PLUGIN_REGISTRY::Instance()->AllPlugins() )
{
PLUGIN::RELEASER pi( plugin.m_createFunc() );
if( !pi )
continue;
if( pi->GetFootprintFileDesc().m_FileExtensions.empty() )
continue;
if( pi->CanReadFootprint( fn.GetFullPath() ) )
{
fileType = plugin.m_type;
break;
}
}
if( fileType == IO_MGR::FILE_TYPE_NONE )
{
@ -265,16 +171,18 @@ FOOTPRINT* FOOTPRINT_EDIT_FRAME::ImportFootprint( const wxString& aName )
}
FOOTPRINT* footprint = nullptr;
wxString footprintName;
try
{
footprint = try_load_footprint( fn, fileType, footprintName );
PLUGIN::RELEASER pi( IO_MGR::PluginFind( fileType ) );
footprint = pi->ImportFootprint( fn.GetFullPath(), footprintName);
if( !footprint )
{
wxString msg = wxString::Format( _( "Unable to load footprint '%s' from '%s'" ),
footprintName,
fn.GetFullPath() );
footprintName, fn.GetFullPath() );
DisplayError( this, msg );
return nullptr;
}

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2011-2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -56,6 +56,12 @@
// plugins coexisting.
wxString PLUGIN_FILE_DESC::FileFilter() const
{
return wxGetTranslation( m_Description ) + AddFileExtListToFilter( m_FileExtensions );
}
PLUGIN* IO_MGR::PluginFind( PCB_FILE_T aFileType )
{
// This implementation is subject to change, any magic is allowed here.
@ -107,21 +113,6 @@ IO_MGR::PCB_FILE_T IO_MGR::EnumFromStr( const wxString& aType )
}
const wxString IO_MGR::GetFileExtension( PCB_FILE_T aFileType )
{
wxString ext = wxEmptyString;
PLUGIN* plugin = PluginFind( aFileType );
if( plugin != nullptr )
{
ext = plugin->GetFileExtension();
PluginRelease( plugin );
}
return ext;
}
IO_MGR::PCB_FILE_T IO_MGR::GuessPluginTypeFromLibPath( const wxString& aLibPath )
{
PCB_FILE_T ret = KICAD_SEXP; // default guess, unless detected otherwise.
@ -193,57 +184,62 @@ void IO_MGR::Save( PCB_FILE_T aFileType, const wxString& aFileName, BOARD* aBoar
// These text strings are "truth" for identifying the plugins. If you change the spellings,
// you will obsolete library tables, so don't do it. Additions are OK.
static IO_MGR::REGISTER_PLUGIN registerEaglePlugin(
IO_MGR::EAGLE,
wxT("Eagle"),
[]() -> PLUGIN* { return new EAGLE_PLUGIN; } );
// clang-format off
static IO_MGR::REGISTER_PLUGIN registerKicadPlugin(
IO_MGR::KICAD_SEXP,
wxT("KiCad"),
wxT( "KiCad" ),
[]() -> PLUGIN* { return new PCB_PLUGIN; } );
static IO_MGR::REGISTER_PLUGIN registerPcadPlugin(
IO_MGR::PCAD,
wxT("P-Cad"),
[]() -> PLUGIN* { return new PCAD_PLUGIN; } );
static IO_MGR::REGISTER_PLUGIN registerLegacyPlugin(
IO_MGR::LEGACY,
wxT( "Legacy" ),
[]() -> PLUGIN* { return new LEGACY_PLUGIN; } );
static IO_MGR::REGISTER_PLUGIN registerFabmasterPlugin(
IO_MGR::FABMASTER,
wxT( "Fabmaster" ),
[]() -> PLUGIN* { return new FABMASTER_PLUGIN; } );
static IO_MGR::REGISTER_PLUGIN registerAltiumDesignerPlugin(
IO_MGR::ALTIUM_DESIGNER,
wxT( "Altium Designer" ),
[]() -> PLUGIN* { return new ALTIUM_DESIGNER_PLUGIN; } );
static IO_MGR::REGISTER_PLUGIN registerAltiumCircuitStudioPlugin(
IO_MGR::ALTIUM_CIRCUIT_STUDIO,
wxT( "Altium Circuit Studio" ),
[]() -> PLUGIN* { return new ALTIUM_CIRCUIT_STUDIO_PLUGIN; } );
// Keep non-KiCad plugins in alphabetical order
static IO_MGR::REGISTER_PLUGIN registerAltiumCircuitMakerPlugin(
IO_MGR::ALTIUM_CIRCUIT_MAKER,
wxT( "Altium Circuit Maker" ),
[]() -> PLUGIN* { return new ALTIUM_CIRCUIT_MAKER_PLUGIN; } );
static IO_MGR::REGISTER_PLUGIN registerSolidworksPCBPlugin(
IO_MGR::SOLIDWORKS_PCB,
wxT( "Solidworks PCB" ),
[]() -> PLUGIN* { return new SOLIDWORKS_PCB_PLUGIN; } );
static IO_MGR::REGISTER_PLUGIN registerAltiumCircuitStudioPlugin(
IO_MGR::ALTIUM_CIRCUIT_STUDIO,
wxT( "Altium Circuit Studio" ),
[]() -> PLUGIN* { return new ALTIUM_CIRCUIT_STUDIO_PLUGIN; } );
static IO_MGR::REGISTER_PLUGIN registerAltiumDesignerPlugin(
IO_MGR::ALTIUM_DESIGNER,
wxT( "Altium Designer" ),
[]() -> PLUGIN* { return new ALTIUM_DESIGNER_PLUGIN; } );
static IO_MGR::REGISTER_PLUGIN registerCadstarArchivePlugin(
IO_MGR::CADSTAR_PCB_ARCHIVE,
wxT( "CADSTAR PCB Archive" ),
[]() -> PLUGIN* { return new CADSTAR_PCB_ARCHIVE_PLUGIN; } );
static IO_MGR::REGISTER_PLUGIN registerLegacyPlugin(
IO_MGR::LEGACY,
wxT("Legacy"),
[]() -> PLUGIN* { return new LEGACY_PLUGIN; } );
static IO_MGR::REGISTER_PLUGIN registerEaglePlugin(
IO_MGR::EAGLE,
wxT( "Eagle" ),
[]() -> PLUGIN* { return new EAGLE_PLUGIN; } );
static IO_MGR::REGISTER_PLUGIN registerFabmasterPlugin(
IO_MGR::FABMASTER,
wxT( "Fabmaster" ),
[]() -> PLUGIN* { return new FABMASTER_PLUGIN; } );
static IO_MGR::REGISTER_PLUGIN registerGPCBPlugin(
IO_MGR::GEDA_PCB,
wxT("GEDA/Pcb"),
wxT( "GEDA/Pcb" ),
[]() -> PLUGIN* { return new GPCB_PLUGIN; } );
static IO_MGR::REGISTER_PLUGIN registerPcadPlugin(
IO_MGR::PCAD,
wxT( "P-Cad" ),
[]() -> PLUGIN* { return new PCAD_PLUGIN; } );
static IO_MGR::REGISTER_PLUGIN registerSolidworksPCBPlugin(
IO_MGR::SOLIDWORKS_PCB,
wxT( "Solidworks PCB" ),
[]() -> PLUGIN* { return new SOLIDWORKS_PCB_PLUGIN; } );
// clang-format on

View File

@ -25,12 +25,9 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <richio.h>
#include <map>
#include <functional>
#include <wx/time.h>
#include <config.h>
#include <vector>
#include <wx/arrstr.h>
#include <i18n_utility.h>
class BOARD;
class PLUGIN;
@ -48,21 +45,21 @@ public:
/**
* The set of file types that the IO_MGR knows about, and for which there has been a
* plugin written.
* plugin written, in alphabetical order.
*/
enum PCB_FILE_T
{
LEGACY, ///< Legacy Pcbnew file formats prior to s-expression.
KICAD_SEXP, ///< S-expression Pcbnew file format.
EAGLE,
PCAD,
FABMASTER,
ALTIUM_DESIGNER,
ALTIUM_CIRCUIT_STUDIO,
LEGACY, ///< Legacy Pcbnew file formats prior to s-expression.
ALTIUM_CIRCUIT_MAKER,
SOLIDWORKS_PCB,
ALTIUM_CIRCUIT_STUDIO,
ALTIUM_DESIGNER,
CADSTAR_PCB_ARCHIVE,
EAGLE,
FABMASTER,
GEDA_PCB, ///< Geda PCB file formats.
PCAD,
SOLIDWORKS_PCB,
// add your type here.
// etc.
@ -178,14 +175,6 @@ public:
*/
static PCB_FILE_T EnumFromStr( const wxString& aFileType );
/**
* Return the file extension for \a aFileType.
*
* @param aFileType The #PCB_FILE_T type.
* @return the file extension for \a aFileType or an empty string if \a aFileType is invalid.
*/
static const wxString GetFileExtension( PCB_FILE_T aFileType );
/**
* Return a plugin type given a footprint library's libPath.
*/
@ -239,6 +228,33 @@ public:
};
/**
* Container that describes file type info
*/
struct PLUGIN_FILE_DESC
{
wxString m_Description; ///< Description shown in the file picker dialog
std::vector<std::string> m_FileExtensions; ///< Filter used for file pickers if m_IsFile is true
std::vector<std::string> m_ExtensionsInDir; ///< In case of folders: extensions of files inside
bool m_IsFile; ///< Whether the library is a folder or a file
PLUGIN_FILE_DESC( const wxString& aDescription, const std::vector<std::string>& aFileExtensions,
const std::vector<std::string>& aExtsInFolder = {}, bool aIsFile = true ) :
m_Description( aDescription ),
m_FileExtensions( aFileExtensions ), m_ExtensionsInDir( aExtsInFolder ),
m_IsFile( aIsFile )
{
}
/**
* @return translated description + wildcards string for file dialogs.
*/
wxString FileFilter() const;
operator bool() const { return !m_Description.empty(); }
};
/**
* A base class that #BOARD loading and saving plugins should derive from.
*
@ -276,9 +292,37 @@ public:
virtual const wxString PluginName() const = 0;
/**
* Returns the file extension for the PLUGIN.
* Returns board file description for the PLUGIN.
*/
virtual const wxString GetFileExtension() const = 0;
virtual PLUGIN_FILE_DESC GetBoardFileDesc() const;
/**
* Returns footprint file description for the PLUGIN.
*/
virtual PLUGIN_FILE_DESC GetFootprintFileDesc() const;
/**
* Returns footprint library description for the PLUGIN.
*/
virtual PLUGIN_FILE_DESC GetFootprintLibDesc() const;
/**
* Checks if this PLUGIN can read the specified board file.
* If not overriden, extension check is used.
*/
virtual bool CanReadBoard( const wxString& aFileName ) const;
/**
* Checks if this PLUGIN can read a footprint from specified file or directory.
* If not overriden, extension check is used.
*/
virtual bool CanReadFootprint( const wxString& aFileName ) const;
/**
* Checks if this PLUGIN can read footprint library from specified file or directory.
* If not overriden, extension check is used.
*/
virtual bool CanReadFootprintLib( const wxString& aFileName ) const;
/**
* Registers a KIDIALOG callback for collecting info from the user.
@ -396,6 +440,26 @@ public:
virtual void PrefetchLib( const wxString& aLibraryPath,
const STRING_UTF8_MAP* aProperties = nullptr );
/**
* Load a single footprint from @a aFootprintPath and put its name in @a aFootprintNameOut.
* If this is a footprint library, the first footprint should be loaded.
* The default implementation uses FootprintEnumerate and FootprintLoad to load first footprint.
*
* @param aLibraryPath is a path of the footprint file.
* @param aFootprintNameOut is the name output of the loaded footprint.
* @param aProperties is an associative array that can be used to tell the loader
* implementation to do something special, because it can take
* any number of additional named tuning arguments that the plugin
* is known to support. The caller continues to own this object
* (plugin may not delete it), and plugins should expect it to be
* optionally NULL.
* @return the #FOOTPRINT object if found, caller owns it, else NULL if not found.
*
* @throw IO_ERROR if the footprint cannot be found or read.
*/
virtual FOOTPRINT* ImportFootprint( const wxString& aFootprintPath, wxString& aFootprintNameOut,
const STRING_UTF8_MAP* aProperties = nullptr );
/**
* Load a footprint having @a aFootprintName from the @a aLibraryPath containing a library
* format that this PLUGIN knows about.
@ -412,7 +476,7 @@ public:
* @param aKeepUUID = true to keep initial items UUID, false to set new UUID
* normally true if loaded in the footprint editor, false
* if loaded in the board editor. Make sense only in kicad_plugin
* @return the #FOOTPRINT object if found caller owns it, else NULL if not found.
* @return the #FOOTPRINT object if found, caller owns it, else NULL if not found.
*
* @throw IO_ERROR if the library cannot be found or read. No exception is thrown in
* the case where \a aFootprintName cannot be found.

View File

@ -1,8 +1,9 @@
#include "io_mgr.h"
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2011-2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2016-2020 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -22,9 +23,15 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <unordered_set>
#include <io_mgr.h>
#include <ki_exception.h>
#include <string_utf8_map.h>
#include <wx/log.h>
#include <wx/filename.h>
#include <wx/translation.h>
#include <wx/filename.h>
#include <wx/dir.h>
#define FMT_UNIMPLEMENTED wxT( "Plugin \"%s\" does not implement the \"%s\" function." )
@ -34,6 +41,106 @@
wxString::FromUTF8( aCaller ) ) );
PLUGIN_FILE_DESC PLUGIN::GetBoardFileDesc() const
{
return PLUGIN_FILE_DESC( wxEmptyString, {} );
}
PLUGIN_FILE_DESC PLUGIN::GetFootprintFileDesc() const
{
return PLUGIN_FILE_DESC( wxEmptyString, {} );
}
PLUGIN_FILE_DESC PLUGIN::GetFootprintLibDesc() const
{
return PLUGIN_FILE_DESC( wxEmptyString, {} );
}
bool PLUGIN::CanReadBoard( const wxString& aFileName ) const
{
const std::vector<std::string>& exts = GetBoardFileDesc().m_FileExtensions;
wxString fileExt = wxFileName( aFileName ).GetExt().MakeLower();
for( const wxString& ext : exts )
{
if( fileExt == ext.Lower() )
return true;
}
return false;
}
bool PLUGIN::CanReadFootprint( const wxString& aFileName ) const
{
const std::vector<std::string>& exts = GetFootprintFileDesc().m_FileExtensions;
wxString fileExt = wxFileName( aFileName ).GetExt().MakeLower();
for( const wxString& ext : exts )
{
if( fileExt == ext.Lower() )
return true;
}
return false;
}
bool PLUGIN::CanReadFootprintLib( const wxString& aFileName ) const
{
const PLUGIN_FILE_DESC& desc = GetFootprintLibDesc();
if( desc.m_IsFile )
{
const std::vector<std::string>& exts = desc.m_FileExtensions;
wxString fileExt = wxFileName( aFileName ).GetExt().MakeLower();
for( const wxString& ext : exts )
{
if( fileExt == ext.Lower() )
return true;
}
}
else
{
wxDir dir( aFileName );
if( !dir.IsOpened() )
return false;
std::vector<std::string> exts = desc.m_ExtensionsInDir;
std::unordered_set<wxString> lowerExts;
for( const std::string& ext : exts )
lowerExts.emplace( wxString( ext ).MakeLower() );
wxString filenameStr;
bool cont = dir.GetFirst( &filenameStr, wxEmptyString, wxDIR_FILES | wxDIR_HIDDEN );
while( cont )
{
wxString ext = wxS( "" );
int idx = filenameStr.Find( '.', true );
if( idx != -1 )
ext = filenameStr.Mid( idx + 1 ).MakeLower();
if( lowerExts.count( ext ) )
return true;
cont = dir.GetNext( &filenameStr );
}
}
return false;
}
BOARD* PLUGIN::LoadBoard( const wxString& aFileName, BOARD* aAppendToMe,
const STRING_UTF8_MAP* aProperties, PROJECT* aProject,
@ -69,6 +176,28 @@ void PLUGIN::PrefetchLib( const wxString&, const STRING_UTF8_MAP* )
}
FOOTPRINT* PLUGIN::ImportFootprint( const wxString& aFootprintPath, wxString& aFootprintNameOut,
const STRING_UTF8_MAP* aProperties )
{
wxArrayString footprintNames;
FootprintEnumerate( footprintNames, aFootprintPath, true, aProperties );
if( footprintNames.empty() )
return nullptr;
if( footprintNames.size() > 1 )
{
wxLogWarning( _( "Selected file contains multiple footprints. Only the first one will be "
"imported." ) );
}
aFootprintNameOut = footprintNames.front();
return FootprintLoad( aFootprintPath, aFootprintNameOut, false, aProperties );
}
const FOOTPRINT* PLUGIN::GetEnumeratedFootprint( const wxString& aLibraryPath,
const wxString& aFootprintName,
const STRING_UTF8_MAP* aProperties )

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 Thomas Pointhuber <thomas.pointhuber@gmx.at>
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -56,9 +56,9 @@ const wxString ALTIUM_CIRCUIT_MAKER_PLUGIN::PluginName() const
}
const wxString ALTIUM_CIRCUIT_MAKER_PLUGIN::GetFileExtension() const
PLUGIN_FILE_DESC ALTIUM_CIRCUIT_MAKER_PLUGIN::GetBoardFileDesc() const
{
return wxT( "CMPcbDoc" );
return PLUGIN_FILE_DESC( _HKI( "Altium Circuit Maker PCB files" ), { "CMPcbDoc" } );
}

View File

@ -33,12 +33,12 @@ class ALTIUM_CIRCUIT_MAKER_PLUGIN : public PLUGIN
public:
const wxString PluginName() const override;
PLUGIN_FILE_DESC GetBoardFileDesc() const override;
BOARD* LoadBoard( const wxString& aFileName, BOARD* aAppendToMe,
const STRING_UTF8_MAP* aProperties, PROJECT* aProject = nullptr,
PROGRESS_REPORTER* aProgressReporter = nullptr ) override;
const wxString GetFileExtension() const override;
long long GetLibraryTimestamp( const wxString& aLibraryPath ) const override
{
// TODO?

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 Thomas Pointhuber <thomas.pointhuber@gmx.at>
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -56,9 +56,9 @@ const wxString ALTIUM_CIRCUIT_STUDIO_PLUGIN::PluginName() const
}
const wxString ALTIUM_CIRCUIT_STUDIO_PLUGIN::GetFileExtension() const
PLUGIN_FILE_DESC ALTIUM_CIRCUIT_STUDIO_PLUGIN::GetBoardFileDesc() const
{
return wxT( "CSPcbDoc" );
return PLUGIN_FILE_DESC( _HKI( "Altium Circuit Studio PCB files" ), { "CSPcbDoc" } );
}

View File

@ -33,12 +33,12 @@ class ALTIUM_CIRCUIT_STUDIO_PLUGIN : public PLUGIN
public:
const wxString PluginName() const override;
PLUGIN_FILE_DESC GetBoardFileDesc() const override;
BOARD* LoadBoard( const wxString& aFileName, BOARD* aAppendToMe,
const STRING_UTF8_MAP* aProperties, PROJECT* aProject,
PROGRESS_REPORTER* aProgressReporter = nullptr ) override;
const wxString GetFileExtension() const override;
long long GetLibraryTimestamp( const wxString& aLibraryPath ) const override
{
// TODO?

View File

@ -53,18 +53,6 @@ ALTIUM_DESIGNER_PLUGIN::~ALTIUM_DESIGNER_PLUGIN()
BOARD* ALTIUM_DESIGNER_PLUGIN::LoadBoard( const wxString& aFileName, BOARD* aAppendToMe,
const STRING_UTF8_MAP* aProperties, PROJECT* aProject,
PROGRESS_REPORTER* aProgressReporter )
}
const wxString ALTIUM_DESIGNER_PLUGIN::GetFileExtension() const
{
return wxT( "PcbDoc" );
}
BOARD* ALTIUM_DESIGNER_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe,
const STRING_UTF8_MAP* aProperties, PROJECT* aProject,
PROGRESS_REPORTER* aProgressReporter )
{
m_props = aProperties;

View File

@ -33,14 +33,22 @@ class ALTIUM_DESIGNER_PLUGIN : public PLUGIN
public:
// -----<PUBLIC PLUGIN API>--------------------------------------------------
const wxString PluginName() const override;
const wxString PluginName() const override { return wxT( "Altium Designer" ); }
PLUGIN_FILE_DESC GetBoardFileDesc() const override
{
return PLUGIN_FILE_DESC( _HKI( "Altium Designer PCB files" ), { "PcbDoc" } );
}
PLUGIN_FILE_DESC GetFootprintLibDesc() const override
{
return PLUGIN_FILE_DESC( _HKI( "Altium PCB footprint library files" ), { "PcbLib" } );
}
BOARD* LoadBoard( const wxString& aFileName, BOARD* aAppendToMe,
const STRING_UTF8_MAP* aProperties, PROJECT* aProject = nullptr,
PROGRESS_REPORTER* aProgressReporter = nullptr ) override;
const wxString GetFileExtension() const override;
long long GetLibraryTimestamp( const wxString& aLibraryPath ) const override;
void FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aLibraryPath,

View File

@ -46,9 +46,9 @@ const wxString SOLIDWORKS_PCB_PLUGIN::PluginName() const
}
const wxString SOLIDWORKS_PCB_PLUGIN::GetFileExtension() const
PLUGIN_FILE_DESC SOLIDWORKS_PCB_PLUGIN::GetBoardFileDesc() const
{
return wxT( "SWPcbDoc" );
return PLUGIN_FILE_DESC( _HKI( "Solidworks PCB files" ), { "SWPcbDoc" } );
}

View File

@ -28,12 +28,12 @@ class SOLIDWORKS_PCB_PLUGIN : public PLUGIN
public:
const wxString PluginName() const override;
PLUGIN_FILE_DESC GetBoardFileDesc() const override;
BOARD* LoadBoard( const wxString& aFileName, BOARD* aAppendToMe,
const STRING_UTF8_MAP* aProperties, PROJECT* aProject = nullptr,
PROGRESS_REPORTER* aProgressReporter = nullptr ) override;
const wxString GetFileExtension() const override;
long long GetLibraryTimestamp( const wxString& aLibraryPath ) const override
{
return 0;

View File

@ -820,6 +820,7 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadComponentLibrary()
footprint->SetPosition( { 0, 0 } ); // KiCad expects library footprints at 0,0
footprint->SetReference( wxT( "REF**" ) );
footprint->SetValue( libID.GetLibItemName() );
footprint->AutoPositionFields();
m_libraryMap.insert( std::make_pair( key, footprint ) );
}
}

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2020 Roberto Fernandez Bautista <roberto.fer.bau@gmail.com>
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@ -81,18 +81,6 @@ void CADSTAR_PCB_ARCHIVE_PLUGIN::clearLoadedFootprints()
}
const wxString CADSTAR_PCB_ARCHIVE_PLUGIN::PluginName() const
{
return wxT( "CADSTAR PCB Archive" );
}
const wxString CADSTAR_PCB_ARCHIVE_PLUGIN::GetFileExtension() const
{
return wxT( "cpa" );
}
std::vector<FOOTPRINT*> CADSTAR_PCB_ARCHIVE_PLUGIN::GetImportedCachedLibraryFootprints()
{
std::vector<FOOTPRINT*> retval;
@ -149,6 +137,39 @@ BOARD* CADSTAR_PCB_ARCHIVE_PLUGIN::LoadBoard( const wxString& aFileName, BOARD*
}
bool CADSTAR_PCB_ARCHIVE_PLUGIN::checkBoardHeader( const wxString& aFileName ) const
{
return fileStartsWithPrefix( aFileName, wxT( "(CADSTARPCB" ), true );
}
bool CADSTAR_PCB_ARCHIVE_PLUGIN::CanReadBoard( const wxString& aFileName ) const
{
if( !PLUGIN::CanReadBoard( aFileName ) )
return false;
return checkBoardHeader( aFileName );
}
bool CADSTAR_PCB_ARCHIVE_PLUGIN::CanReadFootprintLib( const wxString& aFileName ) const
{
if( !PLUGIN::CanReadFootprintLib( aFileName ) )
return false;
return checkBoardHeader( aFileName );
}
bool CADSTAR_PCB_ARCHIVE_PLUGIN::CanReadFootprint( const wxString& aFileName ) const
{
if( !PLUGIN::CanReadFootprint( aFileName ) )
return false;
return checkBoardHeader( aFileName );
}
void CADSTAR_PCB_ARCHIVE_PLUGIN::FootprintEnumerate( wxArrayString& aFootprintNames,
const wxString& aLibraryPath,
bool aBestEfforts,

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2020 Roberto Fernandez Bautista <roberto.fer.bau@gmail.com>
* Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@ -38,13 +38,20 @@
class CADSTAR_PCB_ARCHIVE_PLUGIN : public PLUGIN, public LAYER_REMAPPABLE_PLUGIN
{
public:
const wxString PluginName() const override;
const wxString PluginName() const override { return wxT( "CADSTAR PCB Archive" ); }
BOARD* Load( const wxString& aFileName, BOARD* aAppendToMe,
const STRING_UTF8_MAP* aProperties = nullptr, PROJECT* aProject = nullptr,
PROGRESS_REPORTER* aProgressReporter = nullptr ) override;
PLUGIN_FILE_DESC GetBoardFileDesc() const override
{
return PLUGIN_FILE_DESC( _HKI( "CADSTAR PCB Archive files" ), { "cpa" } );
}
const wxString GetFileExtension() const override;
PLUGIN_FILE_DESC GetFootprintLibDesc() const override { return GetBoardFileDesc(); }
PLUGIN_FILE_DESC GetFootprintFileDesc() const override { return GetFootprintLibDesc(); }
bool CanReadBoard( const wxString& aFileName ) const override;
bool CanReadFootprintLib( const wxString& aFileName ) const override;
bool CanReadFootprint( const wxString& aFileName ) const override;
BOARD* LoadBoard( const wxString& aFileName, BOARD* aAppendToMe,
const STRING_UTF8_MAP* aProperties = nullptr, PROJECT* aProject = nullptr,
@ -68,7 +75,6 @@ public:
*/
void RegisterLayerMappingCallback( LAYER_MAPPING_HANDLER aLayerMappingHandler ) override;
void FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aLibraryPath,
bool aBestEfforts, const STRING_UTF8_MAP* aProperties = nullptr ) override;
@ -107,6 +113,8 @@ private:
BOARD* m_board;
std::vector<FOOTPRINT*> m_loaded_footprints;
bool m_show_layer_mapping_warnings;
bool checkBoardHeader( const wxString& aFileName ) const;
};
#endif // CADSTAR_ARCHIVE_PLUGIN_H_

View File

@ -57,6 +57,7 @@ Load() TODO's
#include <wx/filename.h>
#include <wx/log.h>
#include <wx/wfstream.h>
#include <wx/txtstrm.h>
#include <convert_basic_shapes_to_polygon.h>
#include <string_utils.h>
@ -243,15 +244,49 @@ EAGLE_PLUGIN::~EAGLE_PLUGIN()
}
const wxString EAGLE_PLUGIN::PluginName() const
bool EAGLE_PLUGIN::CanReadBoard( const wxString& aFileName ) const
{
return wxT( "Eagle" );
if( !PLUGIN::CanReadBoard( aFileName ) )
return false;
return checkHeader( aFileName );
}
const wxString EAGLE_PLUGIN::GetFileExtension() const
bool EAGLE_PLUGIN::CanReadFootprintLib( const wxString& aFileName ) const
{
return wxT( "brd" );
if( !PLUGIN::CanReadFootprintLib( aFileName ) )
return false;
return checkHeader( aFileName );
}
bool EAGLE_PLUGIN::CanReadFootprint( const wxString& aFileName ) const
{
return CanReadFootprintLib( aFileName );
}
bool EAGLE_PLUGIN::checkHeader(const wxString& aFileName) const
{
wxFileInputStream input( aFileName );
if( !input.IsOk() )
return false;
wxTextInputStream text( input );
for( int i = 0; i < 3; i++ )
{
if( input.Eof() )
return false;
if( text.ReadLine().Lower().Contains( "eagle" ) )
return true;
}
return false;
}

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2012-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2012-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -129,7 +129,23 @@ struct ERULES
class EAGLE_PLUGIN : public PLUGIN, public LAYER_REMAPPABLE_PLUGIN
{
public:
const wxString PluginName() const override;
const wxString PluginName() const { return wxT( "Eagle" ); }
PLUGIN_FILE_DESC GetBoardFileDesc() const override
{
return PLUGIN_FILE_DESC( _HKI( "Eagle ver. 6.x XML PCB files" ), { "brd" } );
}
PLUGIN_FILE_DESC GetFootprintLibDesc() const override
{
return PLUGIN_FILE_DESC( _HKI( "Eagle ver. 6.x XML library files" ), { "lbr" } );
}
PLUGIN_FILE_DESC GetFootprintFileDesc() const override { return GetFootprintLibDesc(); }
bool CanReadBoard( const wxString& aFileName ) const override;
bool CanReadFootprintLib( const wxString& aFileName ) const override;
bool CanReadFootprint( const wxString& aFileName ) const override;
BOARD* LoadBoard( const wxString& aFileName, BOARD* aAppendToMe,
const STRING_UTF8_MAP* aProperties = nullptr, PROJECT* aProject = nullptr,
@ -137,8 +153,6 @@ public:
std::vector<FOOTPRINT*> GetImportedCachedLibraryFootprints() override;
const wxString GetFileExtension() const override;
void FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aLibraryPath,
bool aBestEfforts, const STRING_UTF8_MAP* aProperties = nullptr) override;
@ -180,6 +194,8 @@ private:
/// initialize PLUGIN like a constructor would, and futz with fresh BOARD if needed.
void init( const STRING_UTF8_MAP* aProperties );
bool checkHeader( const wxString& aFileName ) const;
void checkpoint();
void clear_cu_map();

View File

@ -51,9 +51,9 @@ const wxString FABMASTER_PLUGIN::PluginName() const
}
const wxString FABMASTER_PLUGIN::GetFileExtension() const
PLUGIN_FILE_DESC FABMASTER_PLUGIN::GetBoardFileDesc() const
{
return wxT( "txt" );
return PLUGIN_FILE_DESC( _HKI( "Fabmaster PCB files" ), { "txt", "fab" } );
}

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -37,13 +37,13 @@ class FABMASTER_PLUGIN : public PLUGIN
{
public:
const wxString PluginName() const override;
PLUGIN_FILE_DESC GetBoardFileDesc() const override;
BOARD* LoadBoard( const wxString& aFileName, BOARD* aAppendToMe,
const STRING_UTF8_MAP* aProperties = nullptr, PROJECT* aProject = nullptr,
PROGRESS_REPORTER* aProgressReporter = nullptr ) override;
const wxString GetFileExtension() const override;
long long GetLibraryTimestamp( const wxString& aLibraryPath ) const override
{
// No support for libraries....

View File

@ -46,6 +46,7 @@
#include <wx/filename.h>
#include <wx/wfstream.h>
#include <boost/ptr_container/ptr_map.hpp>
#include <filter_reader.h>
static inline long parseInt( const wxString& aValue, double aScalar )
@ -833,6 +834,31 @@ void GPCB_PLUGIN::validateCache( const wxString& aLibraryPath, bool checkModifie
}
FOOTPRINT* GPCB_PLUGIN::ImportFootprint( const wxString& aFootprintPath,
wxString& aFootprintNameOut,
const STRING_UTF8_MAP* aProperties )
{
wxFileName fn( aFootprintPath );
FILE_LINE_READER freader( aFootprintPath );
WHITESPACE_FILTER_READER reader( freader );
IO_MGR::PCB_FILE_T file_type;
reader.ReadLine();
char* line = reader.Line();
if( !line )
return nullptr;
if( strncasecmp( line, "Element", strlen( "Element" ) ) != 0 )
return nullptr;
aFootprintNameOut = fn.GetName();
return FootprintLoad( fn.GetPath(), aFootprintNameOut );
}
void GPCB_PLUGIN::FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aLibraryPath,
bool aBestEfforts, const STRING_UTF8_MAP* aProperties )
{

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2012-2020 Wayne Stambaugh <stambaughw@verizon.net>
* Copyright (C) 2012-2017 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2012-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -48,14 +48,23 @@ class GPCB_PLUGIN : public PLUGIN
public:
const wxString PluginName() const override
{
return wxT( "Geda PCB" );
return wxT( "gEDA PCB" );
}
const wxString GetFileExtension() const override
PLUGIN_FILE_DESC GetFootprintFileDesc() const override
{
return wxT( "fp" );
return PLUGIN_FILE_DESC( _HKI( "gEDA PCB footprint file" ), { "fp" } );
}
PLUGIN_FILE_DESC GetFootprintLibDesc() const override
{
return PLUGIN_FILE_DESC( _HKI( "gEDA PCB footprint library directory" ), {}, { "fp" },
false );
}
FOOTPRINT* ImportFootprint( const wxString& aFootprintPath, wxString& aFootprintNameOut,
const STRING_UTF8_MAP* aProperties ) override;
void FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aLibraryPath,
bool aBestEfforts,
const STRING_UTF8_MAP* aProperties = nullptr ) override;

View File

@ -51,6 +51,7 @@
#include <progress_reporter.h>
#include <wildcards_and_files_ext.h>
#include <wx/dir.h>
#include <wx/ffile.h>
#include <wx/log.h>
// For some reason wxWidgets is built with wxUSE_BASE64 unset so expose the wxWidgets
@ -58,6 +59,7 @@
#define wxUSE_BASE64 1
#include <wx/base64.h>
#include <wx/mstream.h>
#include <filter_reader.h>
using namespace PCB_KEYS_T;
@ -267,6 +269,19 @@ long long FP_CACHE::GetTimestamp( const wxString& aLibPath )
}
bool PCB_PLUGIN::CanReadBoard( const wxString& aFileName ) const
{
if( !PLUGIN::CanReadBoard( aFileName ) )
return false;
FILE_LINE_READER reader( aFileName );
PCB_PARSER parser( &reader, nullptr, m_queryUserCallback );
return parser.IsValidBoardHeader();
}
void PCB_PLUGIN::SaveBoard( const wxString& aFileName, BOARD* aBoard,
const STRING_UTF8_MAP* aProperties )
{
@ -2424,6 +2439,23 @@ bool PCB_PLUGIN::FootprintExists( const wxString& aLibraryPath, const wxString&
}
FOOTPRINT* PCB_PLUGIN::ImportFootprint( const wxString& aFootprintPath, wxString& aFootprintNameOut,
const STRING_UTF8_MAP* aProperties )
{
wxString fcontents;
wxFFile f( aFootprintPath );
if( !f.IsOpened() )
return nullptr;
f.ReadAll( &fcontents );
aFootprintNameOut = wxFileName( aFootprintPath ).GetName();
return dynamic_cast<FOOTPRINT*>( Parse( fcontents ) );
}
FOOTPRINT* PCB_PLUGIN::FootprintLoad( const wxString& aLibraryPath,
const wxString& aFootprintName,
bool aKeepUUID,

View File

@ -26,6 +26,7 @@
#define PCB_PLUGIN_H
#include <io_mgr.h>
#include <richio.h>
#include <string>
#include <layer_ids.h>
#include <boost/ptr_container/ptr_map.hpp>
@ -267,13 +268,23 @@ public:
return wxT( "KiCad" );
}
const wxString GetFileExtension() const override
PLUGIN_FILE_DESC GetBoardFileDesc() const override
{
// Would have used wildcards_and_files_ext.cpp's KiCadPcbFileExtension,
// but to be pure, a plugin should not assume that it will always be linked
// with the core of the Pcbnew code. (Might someday be a DLL/DSO.) Besides,
// file extension policy should be controlled by the plugin.
return wxT( "kicad_pcb" );
return PLUGIN_FILE_DESC( _HKI( "KiCad printed circuit board files" ), { "kicad_pcb" } );
}
PLUGIN_FILE_DESC GetFootprintFileDesc() const override
{
return PLUGIN_FILE_DESC( _HKI( "KiCad footprint file" ), { "kicad_mod" } );
}
PLUGIN_FILE_DESC GetFootprintLibDesc() const override
{
return PLUGIN_FILE_DESC( _HKI( "KiCad footprint files" ), {}, { "kicad_mod" }, false );
}
void SetQueryUserCallback( std::function<bool( wxString aTitle, int aIcon, wxString aMessage,
@ -282,6 +293,8 @@ public:
m_queryUserCallback = std::move( aCallback );
}
bool CanReadBoard( const wxString& aFileName ) const override;
void SaveBoard( const wxString& aFileName, BOARD* aBoard,
const STRING_UTF8_MAP* aProperties = nullptr ) override;
@ -302,6 +315,9 @@ public:
bool FootprintExists( const wxString& aLibraryPath, const wxString& aFootprintName,
const STRING_UTF8_MAP* aProperties = nullptr ) override;
FOOTPRINT* ImportFootprint( const wxString& aFootprintPath, wxString& aFootprintNameOut,
const STRING_UTF8_MAP* aProperties = nullptr ) override;
FOOTPRINT* FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName,
bool aKeepUUID = false,
const STRING_UTF8_MAP* aProperties = nullptr ) override;

View File

@ -65,11 +65,16 @@
#include <wx/ffile.h>
#include <wx/log.h>
#include <wx/string.h>
#include <wx/filename.h>
#include <wx/wfstream.h>
#include <wx/txtstrm.h>
#include <boost/ptr_container/ptr_map.hpp>
#include <string_utils.h>
#include <locale_io.h>
#include <macros.h>
#include <string_utf8_map.h>
#include <filter_reader.h>
#include <zones.h>
#include <board.h>
@ -405,6 +410,53 @@ static inline long hexParse( const char* next, const char** out = nullptr )
}
bool LEGACY_PLUGIN::CanReadBoard( const wxString& aFileName ) const
{
if( !PLUGIN::CanReadBoard( aFileName ) )
return false;
wxFileInputStream input( aFileName );
if( !input.IsOk() || input.Eof() )
return false;
wxTextInputStream text( input );
wxString line = text.ReadLine();
return line.StartsWith( wxS( "PCBNEW" ) );
}
bool LEGACY_PLUGIN::CanReadFootprint( const wxString& aFileName ) const
{
if( !PLUGIN::CanReadFootprint( aFileName ) )
return false;
FILE_LINE_READER freader( aFileName );
WHITESPACE_FILTER_READER reader( freader );
IO_MGR::PCB_FILE_T file_type;
reader.ReadLine();
char* line = reader.Line();
if( !line )
return false;
if( !strncasecmp( line, FOOTPRINT_LIBRARY_HEADER, FOOTPRINT_LIBRARY_HEADER_CNT ) )
{
while( reader.ReadLine() )
{
if( !strncasecmp( line, "$MODULE", strlen( "$MODULE" ) ) )
{
return true;
}
}
}
return false;
}
BOARD* LEGACY_PLUGIN::LoadBoard( const wxString& aFileName, BOARD* aAppendToMe,
const STRING_UTF8_MAP* aProperties, PROJECT* aProject,
PROGRESS_REPORTER* aProgressReporter )
@ -2883,9 +2935,6 @@ void LEGACY_PLUGIN::init( const STRING_UTF8_MAP* aProperties )
*/
#include <boost/ptr_container/ptr_map.hpp>
#include <wx/filename.h>
typedef boost::ptr_map< std::string, FOOTPRINT > FOOTPRINT_MAP;

View File

@ -26,6 +26,7 @@
*/
#include <io_mgr.h>
#include <richio.h>
#include <string>
#include <layer_ids.h>
#include <memory>
@ -68,11 +69,21 @@ public:
return wxT( "KiCad-Legacy" );
}
const wxString GetFileExtension() const override
PLUGIN_FILE_DESC GetBoardFileDesc() const override
{
return wxT( "brd" );
return PLUGIN_FILE_DESC( _HKI( "Eagle ver. 6.x XML PCB files" ), { "brd" } );
}
PLUGIN_FILE_DESC GetFootprintLibDesc() const override
{
return PLUGIN_FILE_DESC( _HKI( "Legacy footprint library files" ), { "mod" } );
}
PLUGIN_FILE_DESC GetFootprintFileDesc() const override { return GetFootprintLibDesc(); }
bool CanReadBoard( const wxString& aFileName ) const override;
bool CanReadFootprint( const wxString& aFileName ) const override;
BOARD* LoadBoard( const wxString& aFileName, BOARD* aAppendToMe,
const STRING_UTF8_MAP* aProperties = nullptr, PROJECT* aProject = nullptr,
PROGRESS_REPORTER* aProgressReporter = nullptr ) override;
@ -200,7 +211,7 @@ protected:
///< with this scale factor
double diskToBiu; ///< convert from disk engineering units to BIUs
///< with this scale factor
///< with this scale factor
};
#endif // LEGACY_PLUGIN_H_

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2012 Alexander Lunev <al.lunev@yahoo.com>
* Copyright (C) 2012-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2012-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -60,9 +60,9 @@ const wxString PCAD_PLUGIN::PluginName() const
}
const wxString PCAD_PLUGIN::GetFileExtension() const
PLUGIN_FILE_DESC PCAD_PLUGIN::GetBoardFileDesc() const
{
return wxT( "pcb" );
return PLUGIN_FILE_DESC( _HKI( "P-Cad 200x ASCII PCB files" ), { "pcb" } );
}

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2012 Alexander Lunev <al.lunev@yahoo.com>
* Copyright (C) 2012-2020 KiCad Developers, see AUTHORS.TXT for contributors.
* Copyright (C) 2012-2023 KiCad Developers, see AUTHORS.TXT for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -40,12 +40,12 @@ public:
const wxString PluginName() const override;
PLUGIN_FILE_DESC GetBoardFileDesc() const override;
BOARD* LoadBoard( const wxString& aFileName, BOARD* aAppendToMe,
const STRING_UTF8_MAP* aProperties = nullptr, PROJECT* aProject = nullptr,
PROGRESS_REPORTER* aProgressReporter = nullptr ) override;
const wxString GetFileExtension() const override;
long long GetLibraryTimestamp( const wxString& aLibraryPath ) const override
{
// No support for libraries....

View File

@ -38,7 +38,7 @@ static KEYWORD empty_keywords[1] = {};
static const char ACCEL_ASCII_KEYWORD[] = "ACCEL_ASCII";
void LoadInputFile( const wxString& aFileName, wxXmlDocument* aXmlDoc )
void LoadInputFile( const wxString& aFileName, wxXmlDocument* aXmlDoc )
{
char line[sizeof( ACCEL_ASCII_KEYWORD )];
int tok;

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2012 NBEE Embedded Systems, Miguel Angel Ajo <miguelangel@nbee.es>
* Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -99,8 +99,9 @@ Therefore please help gather the subset of C++ functions for this class that do
throw and add them here, before the class declarations.
*/
HANDLE_EXCEPTIONS(PLUGIN::Load)
HANDLE_EXCEPTIONS(PLUGIN::Save)
HANDLE_EXCEPTIONS(PLUGIN::LoadBoard)
HANDLE_EXCEPTIONS(PLUGIN::SaveBoard)
HANDLE_EXCEPTIONS(PLUGIN::ImportFootprint)
HANDLE_EXCEPTIONS(PLUGIN::FootprintEnumerate)
HANDLE_EXCEPTIONS(PLUGIN::FootprintLoad)
HANDLE_EXCEPTIONS(PLUGIN::FootprintSave)

View File

@ -66,9 +66,9 @@ using namespace std::placeholders;
// files.cpp
extern bool AskLoadBoardFileName( PCB_EDIT_FRAME* aParent, int* aCtl, wxString* aFileName,
bool aKicadFilesOnly = false );
extern IO_MGR::PCB_FILE_T plugin_type( const wxString& aFileName, int aCtl );
extern bool AskLoadBoardFileName( PCB_EDIT_FRAME* aParent, wxString* aFileName, int aCtl = 0 );
extern IO_MGR::PCB_FILE_T FindBoardPlugin( const wxString& aFileName, int aCtl = 0 );
PCB_CONTROL::PCB_CONTROL() :
@ -1007,7 +1007,6 @@ int PCB_CONTROL::Paste( const TOOL_EVENT& aEvent )
int PCB_CONTROL::AppendBoardFromFile( const TOOL_EVENT& aEvent )
{
int open_ctl;
wxString fileName;
PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame );
@ -1016,10 +1015,10 @@ int PCB_CONTROL::AppendBoardFromFile( const TOOL_EVENT& aEvent )
return 1;
// Pick a file to append
if( !AskLoadBoardFileName( editFrame, &open_ctl, &fileName, true ) )
if( !AskLoadBoardFileName( editFrame, &fileName, true ) )
return 1;
IO_MGR::PCB_FILE_T pluginType = plugin_type( fileName, open_ctl );
IO_MGR::PCB_FILE_T pluginType = FindBoardPlugin( fileName, KICTL_KICAD_ONLY );
PLUGIN::RELEASER pi( IO_MGR::PluginFind( pluginType ) );
return AppendBoard( *pi, fileName );
@ -1554,15 +1553,13 @@ int PCB_CONTROL::DdAppendBoard( const TOOL_EVENT& aEvent )
{
wxFileName fileName = wxFileName( *aEvent.Parameter<wxString*>() );
int open_ctl = fileName.GetExt() == KiCadPcbFileExtension ? 0 : KICTL_EAGLE_BRD;
PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( m_frame );
if( !editFrame )
return 1;
wxString filePath = fileName.GetFullPath();
IO_MGR::PCB_FILE_T pluginType = plugin_type( filePath, open_ctl );
IO_MGR::PCB_FILE_T pluginType = FindBoardPlugin( filePath );
PLUGIN::RELEASER pi( IO_MGR::PluginFind( pluginType ) );
return AppendBoard( *pi, filePath );