File open/import progress dialogs.

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

Fixes https://gitlab.com/kicad/code/kicad/issues/2166
This commit is contained in:
Jeff Young 2021-06-23 23:53:08 +01:00
parent 1d6ad4a52a
commit 5fa5a73c6d
45 changed files with 643 additions and 158 deletions

View File

@ -167,8 +167,8 @@ FILE_LINE_READER::FILE_LINE_READER( const wxString& aFileName,
if( !m_fp )
{
wxString msg = wxString::Format(
_( "Unable to open filename \"%s\" for reading" ), aFileName.GetData() );
wxString msg = wxString::Format( _( "Unable to open %s for reading." ),
aFileName.GetData() );
THROW_IO_ERROR( msg );
}
@ -195,6 +195,22 @@ FILE_LINE_READER::~FILE_LINE_READER()
}
long int FILE_LINE_READER::FileLength()
{
fseek( m_fp, 0, SEEK_END );
long int fileLength = ftell( m_fp );
rewind( m_fp );
return fileLength;
}
long int FILE_LINE_READER::CurPos()
{
return ftell( m_fp );
}
char* FILE_LINE_READER::ReadLine()
{
m_length = 0;

View File

@ -369,14 +369,6 @@ bool PGM_SINGLE_TOP::OnPgmInit()
App().SetTopWindow( frame ); // wxApp gets a face.
App().SetAppDisplayName( frame->GetAboutTitle() );
// Allocate a slice of time to show the frame and update wxWidgets widgets
// (especially setting valid sizes) after creating frame and before calling
// OpenProjectFiles() that can update/use some widgets.
// The 2 calls to wxSafeYield are needed on wxGTK for best results.
wxSafeYield();
frame->Show();
wxSafeYield();
// Individual frames may provide additional option/switch processing, but for compatibility,
// any positional arguments are treated as a list of files to pass to OpenProjectFiles
frame->ParseArgs( parser );

View File

@ -61,6 +61,7 @@
#include <tools/ee_inspection_tool.h>
#include <paths.h>
#include <wx_filename.h> // For ::ResolvePossibleSymlinks
#include <widgets/progress_reporter.h>
bool SCH_EDIT_FRAME::SaveEEFile( SCH_SHEET* aSheet, bool aSaveUnderNewName )
{
@ -400,6 +401,9 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
SCH_PLUGIN* plugin = SCH_IO_MGR::FindPlugin( schFileType );
SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( plugin );
WX_PROGRESS_REPORTER progressReporter( this, _( "Loading Schematic" ), 1 );
pi->SetProgressReporter( &progressReporter );
bool failedLoad = false;
try
{
@ -1117,20 +1121,19 @@ bool SCH_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType )
try
{
SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( fileType ) );
DIALOG_HTML_REPORTER* reporter = new DIALOG_HTML_REPORTER( this );
DIALOG_HTML_REPORTER errorReporter( this );
WX_PROGRESS_REPORTER progressReporter( this, _( "Importing Schematic" ), 1 );
pi->SetReporter( reporter->m_Reporter );
pi->SetReporter( errorReporter.m_Reporter );
pi->SetProgressReporter( &progressReporter );
Schematic().SetRoot( pi->Load( aFileName, &Schematic() ) );
if( reporter->m_Reporter->HasMessage() )
if( errorReporter.m_Reporter->HasMessage() )
{
reporter->m_Reporter->Flush(); // Build HTML messages
reporter->ShowModal();
errorReporter.m_Reporter->Flush(); // Build HTML messages
errorReporter.ShowModal();
}
pi->SetReporter( &WXLOG_REPORTER::GetInstance() );
delete reporter;
// Non-KiCad schematics do not use a drawing-sheet (or if they do, it works differently
// to KiCad), so set it to an empty one
DS_DATA_MODEL& drawingSheet = DS_DATA_MODEL::GetTheInstance();

View File

@ -38,6 +38,7 @@ class KIWAY;
class LIB_SYMBOL;
class SYMBOL_LIB;
class PROPERTIES;
class PROGRESS_REPORTER;
/**
@ -164,6 +165,11 @@ public:
*/
virtual void SetReporter( REPORTER* aReporter ) {}
/**
* Set an optional progress reporter.
*/
virtual void SetProgressReporter( PROGRESS_REPORTER* aReporter ) {}
/**
* Return the file extension for the #SCH_PLUGIN.
*/

View File

@ -33,6 +33,7 @@
#include <wx/tokenzr.h>
#include <wx/wfstream.h>
#include <wx/xml/xml.h>
#include <wx/msgdlg.h>
#include <symbol_library.h>
#include <plugins/eagle/eagle_parser.h>
@ -60,6 +61,7 @@
#include <schematic.h>
#include <symbol_lib_table.h>
#include <wildcards_and_files_ext.h>
#include <widgets/progress_reporter.h>
// Eagle schematic axes are aligned with x increasing left to right and Y increasing bottom to top
@ -351,7 +353,11 @@ static void eagleToKicadAlignment( EDA_TEXT* aText, int aEagleAlignment, int aRe
}
SCH_EAGLE_PLUGIN::SCH_EAGLE_PLUGIN()
SCH_EAGLE_PLUGIN::SCH_EAGLE_PLUGIN() :
m_progressReporter( nullptr ),
m_doneCount( 0 ),
m_lastProgressCount( 0 ),
m_totalCount( 0 )
{
m_rootSheet = nullptr;
m_currentSheet = nullptr;
@ -390,6 +396,25 @@ int SCH_EAGLE_PLUGIN::GetModifyHash() const
}
void SCH_EAGLE_PLUGIN::checkpoint()
{
const unsigned PROGRESS_DELTA = 5;
if( m_progressReporter )
{
if( ++m_doneCount > m_lastProgressCount + PROGRESS_DELTA )
{
m_progressReporter->SetCurrentProgress(( (double) m_doneCount ) / m_totalCount );
if( !m_progressReporter->KeepRefreshing() )
THROW_IO_ERROR( ( "Open cancelled by user." ) );
m_lastProgressCount = m_doneCount;
}
}
}
SCH_SHEET* SCH_EAGLE_PLUGIN::Load( const wxString& aFileName, SCHEMATIC* aSchematic,
SCH_SHEET* aAppendToMe, const PROPERTIES* aProperties )
{
@ -399,13 +424,21 @@ SCH_SHEET* SCH_EAGLE_PLUGIN::Load( const wxString& aFileName, SCHEMATIC* aSchema
m_filename = aFileName;
m_schematic = aSchematic;
if( m_progressReporter )
{
m_progressReporter->Report( wxString::Format( _( "Loading %s..." ), aFileName ) );
if( !m_progressReporter->KeepRefreshing() )
THROW_IO_ERROR( ( "Open cancelled by user." ) );
}
// Load the document
wxXmlDocument xmlDocument;
wxFFileInputStream stream( m_filename.GetFullPath() );
if( !stream.IsOk() || !xmlDocument.Load( stream ) )
{
THROW_IO_ERROR( wxString::Format( _( "Unable to read file \"%s\"" ),
THROW_IO_ERROR( wxString::Format( _( "Unable to read file '%s'." ),
m_filename.GetFullPath() ) );
}
@ -562,8 +595,68 @@ void SCH_EAGLE_PLUGIN::loadSchematic( wxXmlNode* aSchematicNode )
if( !sheetNode )
return;
auto count_nodes = []( wxXmlNode* aNode ) -> unsigned
{
unsigned count = 0;
while( aNode )
{
count++;
aNode = aNode->GetNext();
}
return count;
};
if( m_progressReporter )
{
m_totalCount = 0;
m_doneCount = 0;
m_totalCount += count_nodes( partNode );
while( libraryNode )
{
NODE_MAP libraryChildren = MapChildren( libraryNode );
wxXmlNode* devicesetNode = getChildrenNodes( libraryChildren, "devicesets" );
while( devicesetNode )
{
NODE_MAP deviceSetChildren = MapChildren( devicesetNode );
wxXmlNode* deviceNode = getChildrenNodes( deviceSetChildren, "devices" );
wxXmlNode* gateNode = getChildrenNodes( deviceSetChildren, "gates" );
m_totalCount += count_nodes( deviceNode ) * count_nodes( gateNode );
devicesetNode = devicesetNode->GetNext();
}
libraryNode = libraryNode->GetNext();
}
// Rewind
libraryNode = getChildrenNodes( schematicChildren, "libraries" );
while( sheetNode )
{
NODE_MAP sheetChildren = MapChildren( sheetNode );
m_totalCount += count_nodes( getChildrenNodes( sheetChildren, "instances" ) );
m_totalCount += count_nodes( getChildrenNodes( sheetChildren, "busses" ) );
m_totalCount += count_nodes( getChildrenNodes( sheetChildren, "nets" ) );
m_totalCount += count_nodes( getChildrenNodes( sheetChildren, "plain" ) );
sheetNode = sheetNode->GetNext();
}
// Rewind
sheetNode = getChildrenNodes( schematicChildren, "sheets" );
}
while( partNode )
{
checkpoint();
std::unique_ptr<EPART> epart = std::make_unique<EPART>( partNode );
// N.B. Eagle parts are case-insensitive in matching but we keep the display case
@ -585,7 +678,6 @@ void SCH_EAGLE_PLUGIN::loadSchematic( wxXmlNode* aSchematicNode )
libraryNode = libraryNode->GetNext();
}
m_pi->SaveLibrary( getLibFileName().GetFullPath() );
}
@ -734,6 +826,8 @@ void SCH_EAGLE_PLUGIN::loadSheet( wxXmlNode* aSheetNode, int aSheetIndex )
while( instanceNode )
{
checkpoint();
loadInstance( instanceNode );
instanceNode = instanceNode->GetNext();
}
@ -746,6 +840,8 @@ void SCH_EAGLE_PLUGIN::loadSheet( wxXmlNode* aSheetNode, int aSheetIndex )
while( busNode )
{
checkpoint();
// Get the bus name
wxString busName = translateEagleBusName( busNode->GetAttribute( "name" ) );
@ -762,6 +858,8 @@ void SCH_EAGLE_PLUGIN::loadSheet( wxXmlNode* aSheetNode, int aSheetIndex )
while( netNode )
{
checkpoint();
// Get the net name and class
wxString netName = netNode->GetAttribute( "name" );
wxString netClass = netNode->GetAttribute( "class" );
@ -792,6 +890,8 @@ void SCH_EAGLE_PLUGIN::loadSheet( wxXmlNode* aSheetNode, int aSheetIndex )
while( plainNode )
{
checkpoint();
wxString nodeName = plainNode->GetName();
if( nodeName == "text" )
@ -1371,8 +1471,8 @@ void SCH_EAGLE_PLUGIN::loadInstance( wxXmlNode* aInstanceNode )
}
EAGLE_LIBRARY* SCH_EAGLE_PLUGIN::loadLibrary(
wxXmlNode* aLibraryNode, EAGLE_LIBRARY* aEagleLibrary )
EAGLE_LIBRARY* SCH_EAGLE_PLUGIN::loadLibrary( wxXmlNode* aLibraryNode,
EAGLE_LIBRARY* aEagleLibrary )
{
NODE_MAP libraryChildren = MapChildren( aLibraryNode );
@ -1396,8 +1496,8 @@ EAGLE_LIBRARY* SCH_EAGLE_PLUGIN::loadLibrary(
wxString prefix = edeviceset.prefix ? edeviceset.prefix.Get() : "";
NODE_MAP aDeviceSetChildren = MapChildren( devicesetNode );
wxXmlNode* deviceNode = getChildrenNodes( aDeviceSetChildren, "devices" );
NODE_MAP deviceSetChildren = MapChildren( devicesetNode );
wxXmlNode* deviceNode = getChildrenNodes( deviceSetChildren, "devices" );
// For each device in the device set:
while( deviceNode )
@ -1418,8 +1518,8 @@ EAGLE_LIBRARY* SCH_EAGLE_PLUGIN::loadLibrary(
unique_ptr<LIB_SYMBOL> kpart( new LIB_SYMBOL( symbolName ) );
// Process each gate in the deviceset for this device.
wxXmlNode* gateNode = getChildrenNodes( aDeviceSetChildren, "gates" );
int gates_count = countChildren( aDeviceSetChildren["gates"], "gate" );
wxXmlNode* gateNode = getChildrenNodes( deviceSetChildren, "gates" );
int gates_count = countChildren( deviceSetChildren["gates"], "gate" );
kpart->SetUnitCount( gates_count );
kpart->LockUnits( true );
@ -1437,10 +1537,11 @@ EAGLE_LIBRARY* SCH_EAGLE_PLUGIN::loadLibrary(
while( gateNode )
{
checkpoint();
EGATE egate = EGATE( gateNode );
aEagleLibrary->GateUnit[edeviceset.name + edevice.name + egate.name] = gateindex;
ispower = loadSymbol( aEagleLibrary->SymbolNodes[egate.symbol], kpart, &edevice,
gateindex, egate.name );

View File

@ -87,6 +87,11 @@ public:
void SetReporter( REPORTER* aReporter ) override { m_reporter = aReporter; }
void SetProgressReporter( PROGRESS_REPORTER* aReporter ) override
{
m_progressReporter = aReporter;
}
const wxString GetFileExtension() const override;
const wxString GetLibraryFileExtension() const override;
@ -99,8 +104,9 @@ public:
bool CheckHeader( const wxString& aFileName ) override;
private:
void checkpoint();
void loadDrawing( wxXmlNode* aDrawingNode );
void loadLayerDefs( wxXmlNode* aLayers );
void loadSchematic( wxXmlNode* aSchematicNode );
@ -228,9 +234,14 @@ private:
EPART_MAP m_partlist;
std::map<wxString, EAGLE_LIBRARY> m_eagleLibs;
SCH_PLUGIN::SCH_PLUGIN_RELEASER m_pi; ///< Plugin to create the KiCad symbol library.
SCH_PLUGIN::SCH_PLUGIN_RELEASER m_pi; ///< PI to create KiCad symbol library.
std::unique_ptr< PROPERTIES > m_properties; ///< Library plugin properties.
PROGRESS_REPORTER* m_progressReporter; ///< optional; may be nullptr
unsigned m_doneCount;
unsigned m_lastProgressCount;
unsigned m_totalCount; ///< for progress reporting
std::map<wxString, int> m_netCounts;
std::map<int, SCH_LAYER_ID> m_layerMap;

View File

@ -55,21 +55,48 @@
#include <sch_plugins/kicad/sch_sexpr_parser.h>
#include <template_fieldnames.h>
#include <trigo.h>
#include <widgets/progress_reporter.h>
using namespace TSCHEMATIC_T;
SCH_SEXPR_PARSER::SCH_SEXPR_PARSER( LINE_READER* aLineReader ) :
SCH_SEXPR_PARSER::SCH_SEXPR_PARSER( LINE_READER* aLineReader, PROGRESS_REPORTER* aProgressReporter,
unsigned aLineCount ) :
SCHEMATIC_LEXER( aLineReader ),
m_requiredVersion( 0 ),
m_fieldId( 0 ),
m_unit( 1 ),
m_convert( 1 )
m_convert( 1 ),
m_progressReporter( aProgressReporter ),
m_lineReader( aLineReader ),
m_lastProgressLine( 0 ),
m_lineCount( aLineCount )
{
}
void SCH_SEXPR_PARSER::checkpoint()
{
const unsigned PROGRESS_DELTA = 250;
if( m_progressReporter )
{
unsigned curLine = m_lineReader->LineNumber();
if( curLine > m_lastProgressLine + PROGRESS_DELTA )
{
m_progressReporter->SetCurrentProgress( ( (double) curLine ) / m_lineCount );
if( !m_progressReporter->KeepRefreshing() )
THROW_IO_ERROR( ( "Open cancelled by user." ) );
m_lastProgressLine = curLine;
}
}
}
bool SCH_SEXPR_PARSER::parseBool()
{
T token = NextTok();
@ -2090,6 +2117,8 @@ void SCH_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet, bool aIsCopyableOnly,
token = NextTok();
checkpoint();
if( !aIsCopyableOnly && token == T_page && m_requiredVersion <= 20200506 )
token = T_paper;

View File

@ -84,6 +84,13 @@ class SCH_SEXPR_PARSER : public SCHEMATIC_LEXER
int m_convert; ///< The current body style being parsed.
wxString m_symbolName; ///< The current symbol name.
PROGRESS_REPORTER* m_progressReporter; // optional; may be nullptr
const LINE_READER* m_lineReader; // for progress reporting
unsigned m_lastProgressLine;
unsigned m_lineCount; // for progress reporting
void checkpoint();
void parseHeader( TSCHEMATIC_T::T aHeaderType, int aFileVersion );
inline long parseHex()
@ -184,7 +191,8 @@ class SCH_SEXPR_PARSER : public SCHEMATIC_LEXER
void parseBusAlias( SCH_SCREEN* aScreen );
public:
SCH_SEXPR_PARSER( LINE_READER* aLineReader = nullptr );
SCH_SEXPR_PARSER( LINE_READER* aLineReader = nullptr,
PROGRESS_REPORTER* aProgressReporter = nullptr, unsigned aLineCount = 0 );
void ParseLib( LIB_SYMBOL_MAP& aSymbolLibMap );

View File

@ -61,6 +61,7 @@
#include <ee_selection.h>
#include <kicad_string.h>
#include <wx_filename.h> // for ::ResolvePossibleSymlinks()
#include <widgets/progress_reporter.h>
using namespace TSCHEMATIC_T;
@ -365,7 +366,8 @@ public:
};
SCH_SEXPR_PLUGIN::SCH_SEXPR_PLUGIN()
SCH_SEXPR_PLUGIN::SCH_SEXPR_PLUGIN() :
m_progressReporter( nullptr )
{
init( NULL );
}
@ -387,6 +389,7 @@ void SCH_SEXPR_PLUGIN::init( SCHEMATIC* aSchematic, const PROPERTIES* aPropertie
m_nextFreeFieldId = 100; // number arbitrarily > MANDATORY_FIELDS or SHEET_MANDATORY_FIELDS
}
SCH_SHEET* SCH_SEXPR_PLUGIN::Load( const wxString& aFileName, SCHEMATIC* aSchematic,
SCH_SHEET* aAppendToMe, const PROPERTIES* aProperties )
{
@ -518,10 +521,10 @@ void SCH_SEXPR_PLUGIN::loadHierarchy( SCH_SHEET* aSheet )
// This was moved out of the try{} block so that any sheets definitionsthat
// the plugin fully parsed before the exception was raised will be loaded.
for( auto aItem : aSheet->GetScreen()->Items().OfType( SCH_SHEET_T ) )
for( SCH_ITEM* aItem : aSheet->GetScreen()->Items().OfType( SCH_SHEET_T ) )
{
wxCHECK2( aItem->Type() == SCH_SHEET_T, /* do nothing */ );
auto sheet = static_cast<SCH_SHEET*>( aItem );
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem );
// Recursion starts here.
loadHierarchy( sheet );
@ -538,7 +541,22 @@ void SCH_SEXPR_PLUGIN::loadFile( const wxString& aFileName, SCH_SHEET* aSheet )
{
FILE_LINE_READER reader( aFileName );
SCH_SEXPR_PARSER parser( &reader );
size_t lineCount = 0;
if( m_progressReporter )
{
m_progressReporter->Report( wxString::Format( _( "Loading %s..." ), aFileName ) );
if( !m_progressReporter->KeepRefreshing() )
THROW_IO_ERROR( ( "Open cancelled by user." ) );
while( reader.ReadLine() )
lineCount++;
reader.Rewind();
}
SCH_SEXPR_PARSER parser( &reader, m_progressReporter, lineCount );
parser.ParseSchematic( aSheet );
}

View File

@ -79,6 +79,11 @@ public:
return wxT( "kicad_sym" );
}
void SetProgressReporter( PROGRESS_REPORTER* aReporter ) override
{
m_progressReporter = aReporter;
}
/**
* The property used internally by the plugin to enable cache buffering which prevents
* the library file from being written every time the cache is changed. This is useful
@ -155,13 +160,15 @@ protected:
int m_version; ///< Version of file being loaded.
int m_nextFreeFieldId;
wxString m_error; ///< For throwing exceptions or errors on partial loads.
wxString m_error; ///< For throwing exceptions or errors on partial
///< loads.
PROGRESS_REPORTER* m_progressReporter;
wxString m_path; ///< Root project path for loading child sheets.
std::stack<wxString> m_currentPath; ///< Stack to maintain nested sheet paths
SCH_SHEET* m_rootSheet; ///< The root sheet of the schematic being loaded..
SCHEMATIC* m_schematic; ///< Passed to Load(), the schematic object being loaded
OUTPUTFORMATTER* m_out; ///< The output formatter for saving SCH_SCREEN objects.
SCH_SHEET* m_rootSheet; ///< The root sheet of the schematic being loaded.
SCHEMATIC* m_schematic;
OUTPUTFORMATTER* m_out; ///< The formatter for saving SCH_SCREEN objects.
SCH_SEXPR_PLUGIN_CACHE* m_cache;
/// initialize PLUGIN like a constructor would.

View File

@ -41,6 +41,9 @@
#include <properties.h>
#include <trace_helpers.h>
#include <trigo.h>
#include <confirm.h>
#include <widgets/progress_reporter.h>
#include <wx_filename.h> // For ::ResolvePossibleSymlinks()
#include <general.h>
#include <sch_bitmap.h>
@ -70,10 +73,8 @@
#include <lib_text.h>
#include <eeschema_id.h> // for MAX_UNIT_COUNT_PER_PACKAGE definition
#include <symbol_lib_table.h> // for PropPowerSymsOnly definition.
#include <confirm.h>
#include <tool/selection.h>
#include <default_values.h> // For some default values
#include <wx_filename.h> // For ::ResolvePossibleSymlinks()
#define Mils2Iu( x ) Mils2iu( x )
@ -582,7 +583,11 @@ public:
};
SCH_LEGACY_PLUGIN::SCH_LEGACY_PLUGIN()
SCH_LEGACY_PLUGIN::SCH_LEGACY_PLUGIN() :
m_progressReporter( nullptr ),
m_lineReader( nullptr ),
m_lastProgressLine( 0 ),
m_lineCount( 0 )
{
init( NULL );
}
@ -604,6 +609,27 @@ void SCH_LEGACY_PLUGIN::init( SCHEMATIC* aSchematic, const PROPERTIES* aProperti
}
void SCH_LEGACY_PLUGIN::checkpoint()
{
const unsigned PROGRESS_DELTA = 250;
if( m_progressReporter )
{
unsigned curLine = m_lineReader->LineNumber();
if( curLine > m_lastProgressLine + PROGRESS_DELTA )
{
m_progressReporter->SetCurrentProgress( ( (double) curLine ) / m_lineCount );
if( !m_progressReporter->KeepRefreshing() )
THROW_IO_ERROR( ( "Open cancelled by user." ) );
m_lastProgressLine = curLine;
}
}
}
SCH_SHEET* SCH_LEGACY_PLUGIN::Load( const wxString& aFileName, SCHEMATIC* aSchematic,
SCH_SHEET* aAppendToMe, const PROPERTIES* aProperties )
{
@ -753,6 +779,22 @@ void SCH_LEGACY_PLUGIN::loadFile( const wxString& aFileName, SCH_SCREEN* aScreen
{
FILE_LINE_READER reader( aFileName );
if( m_progressReporter )
{
m_progressReporter->Report( wxString::Format( _( "Loading %s..." ), aFileName ) );
if( !m_progressReporter->KeepRefreshing() )
THROW_IO_ERROR( ( "Open cancelled by user." ) );
m_lineReader = &reader;
m_lineCount = 0;
while( reader.ReadLine() )
m_lineCount++;
reader.Rewind();
}
loadHeader( reader, aScreen );
LoadContent( reader, aScreen, m_version );
@ -782,6 +824,8 @@ void SCH_LEGACY_PLUGIN::LoadContent( LINE_READER& aReader, SCH_SCREEN* aScreen,
while( aReader.ReadLine() )
{
checkpoint();
char* line = aReader.Line();
while( *line == ' ' )
@ -842,6 +886,8 @@ void SCH_LEGACY_PLUGIN::loadHeader( LINE_READER& aReader, SCH_SCREEN* aScreen )
// Skip all lines until the end of header "EELAYER END" is found
while( aReader.ReadLine() )
{
checkpoint();
line = aReader.Line();
while( *line == ' ' )

View File

@ -82,6 +82,11 @@ public:
return wxT( "lib" );
}
void SetProgressReporter( PROGRESS_REPORTER* aReporter ) override
{
m_progressReporter = aReporter;
}
/**
* The property used internally by the plugin to enable cache buffering which prevents
* the library file from being written every time the cache is changed. This is useful
@ -140,6 +145,7 @@ public:
static void FormatPart( LIB_SYMBOL* aSymbol, OUTPUTFORMATTER& aFormatter );
private:
void checkpoint();
void loadHierarchy( SCH_SHEET* aSheet );
void loadHeader( LINE_READER& aReader, SCH_SCREEN* aScreen );
void loadPageSettings( LINE_READER& aReader, SCH_SCREEN* aScreen );
@ -172,15 +178,19 @@ private:
protected:
int m_version; ///< Version of file being loaded.
/** For throwing exceptions or errors on partial schematic loads. */
wxString m_error;
wxString m_error; ///< For throwing exceptions or errors on partial
///< schematic loads.
PROGRESS_REPORTER* m_progressReporter; ///< optional; may be nullptr
LINE_READER* m_lineReader; ///< for progress reporting
unsigned m_lastProgressLine;
unsigned m_lineCount; ///< for progress reporting
wxString m_path; ///< Root project path for loading child sheets.
std::stack<wxString> m_currentPath; ///< Stack to maintain nested sheet paths
SCH_SHEET* m_rootSheet; ///< The root sheet of the schematic being loaded..
OUTPUTFORMATTER* m_out; ///< The output formatter for saving SCH_SCREEN objects.
SCH_SHEET* m_rootSheet; ///< The root sheet of the schematic being loaded.
OUTPUTFORMATTER* m_out; ///< The formatter for saving SCH_SCREEN objects.
SCH_LEGACY_PLUGIN_CACHE* m_cache;
SCHEMATIC* m_schematic; ///< Passed to Load(), the schematic object being loaded
SCHEMATIC* m_schematic;
/// initialize PLUGIN like a constructor would.
void init( SCHEMATIC* aSchematic, const PROPERTIES* aProperties = nullptr );

View File

@ -131,7 +131,7 @@ std::vector<SYMBOL_ASYNC_LOADER::LOADED_PAIR> SYMBOL_ASYNC_LOADER::worker()
}
if( m_reporter )
m_reporter->AdvancePhase( wxString::Format( _( "Loading library \"%s\"" ), nickname ) );
m_reporter->AdvancePhase( wxString::Format( _( "Loading library %s..." ), nickname ) );
}
return ret;

View File

@ -225,6 +225,9 @@ public:
m_lineNum = 0;
}
long int FileLength();
long int CurPos();
protected:
bool m_iOwn; ///< if I own the file, I'll promise to close it, else not.
FILE* m_fp; ///< I may own this file, but might not.

View File

@ -665,18 +665,13 @@ int KICAD_MANAGER_CONTROL::ShowPlayer( const TOOL_EVENT& aEvent )
filepath = legacy_board.GetFullPath();
}
// Show the frame (and update widgets to set valid sizes),
// after creating player and before calling OpenProjectFiles().
// Useful because loading a complex board and building its internal data can be
// time consuming
player->Show( true );
wxSafeYield();
if( !filepath.IsEmpty() )
{
if( !player->OpenProjectFiles( std::vector<wxString>( 1, filepath ) ) )
return -1;
}
player->Show( true );
}
// Needed on Windows, other platforms do not use it, but it creates no issue

View File

@ -38,6 +38,7 @@
#include <settings/settings_manager.h>
#include <widgets/infobar.h>
#include <widgets/resettable_panel.h>
#include <widgets/progress_reporter.h>
#include <wildcards_and_files_ext.h>
#include "dialog_board_setup.h"
@ -192,7 +193,10 @@ void DIALOG_BOARD_SETUP::OnAuxiliaryAction( wxCommandEvent& event )
try
{
otherBoard = pi->Load( boardFn.GetFullPath(), nullptr, nullptr );
WX_PROGRESS_REPORTER progressReporter( this, _( "Loading PCB" ), 1 );
otherBoard = pi->Load( boardFn.GetFullPath(), nullptr, nullptr, nullptr,
&progressReporter );
if( importDlg.m_LayersOpt->GetValue() )
{

View File

@ -501,7 +501,7 @@ void PANEL_PCBNEW_COLOR_SETTINGS::createPreviewItems()
try
{
pi.DoLoad( reader, m_preview->GetBoard(), nullptr );
pi.DoLoad( reader, m_preview->GetBoard(), nullptr, nullptr, 0 );
}
catch( const IO_ERROR& )
{

View File

@ -25,7 +25,6 @@
#include <confirm.h>
#include <core/arraydim.h>
#include <kicad_string.h>
#include <gestfich.h>
#include <pcb_edit_frame.h>
#include <board_design_settings.h>
@ -48,6 +47,7 @@
#include <kiplatform/app.h>
#include <widgets/appearance_controls.h>
#include <widgets/infobar.h>
#include <widgets/progress_reporter.h>
#include <settings/settings_manager.h>
#include <paths.h>
#include <project/project_file.h>
@ -56,7 +56,6 @@
#include <plugins/cadstar/cadstar_pcb_archive_plugin.h>
#include <plugins/kicad/kicad_plugin.h>
#include <dialogs/dialog_imported_layers.h>
#include <tool/tool_manager.h>
#include <tools/pcb_actions.h>
#include "footprint_info_impl.h"
#include <wx_filename.h> // For ::ResolvePossibleSymlinks()
@ -691,12 +690,13 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
props["page_width"] = xbuf;
props["page_height"] = ybuf;
WX_PROGRESS_REPORTER progressReporter( this, _( "Loading PCB" ), 1 );
#if USE_INSTRUMENTATION
// measure the time to load a BOARD.
unsigned startTime = GetRunningMicroSecs();
#endif
loadedBoard = pi->Load( fullFileName, NULL, &props, &Prj() );
loadedBoard = pi->Load( fullFileName, NULL, &props, &Prj(), &progressReporter );
#if USE_INSTRUMENTATION
unsigned stopTime = GetRunningMicroSecs();

View File

@ -156,14 +156,15 @@ IO_MGR::PCB_FILE_T IO_MGR::GuessPluginTypeFromLibPath( const wxString& aLibPath
BOARD* IO_MGR::Load( PCB_FILE_T aFileType, const wxString& aFileName, BOARD* aAppendToMe,
const PROPERTIES* aProperties, PROJECT* aProject )
const PROPERTIES* aProperties, PROJECT* aProject,
PROGRESS_REPORTER* aProgressReporter )
{
// release the PLUGIN even if an exception is thrown.
PLUGIN::RELEASER pi( PluginFind( aFileType ) );
if( (PLUGIN*) pi ) // test pi->plugin
{
return pi->Load( aFileName, aAppendToMe, aProperties, aProject ); // virtual
return pi->Load( aFileName, aAppendToMe, aProperties, aProject, aProgressReporter );
}
THROW_IO_ERROR( wxString::Format( FMT_NOTFOUND, ShowType( aFileType ).GetData() ) );

View File

@ -37,6 +37,7 @@ class PLUGIN;
class FOOTPRINT;
class PROPERTIES;
class PROJECT;
class PROGRESS_REPORTER;
/**
* A factory which returns an instance of a #PLUGIN.
@ -210,7 +211,8 @@ public:
*/
static BOARD* Load( PCB_FILE_T aFileType, const wxString& aFileName,
BOARD* aAppendToMe = nullptr, const PROPERTIES* aProperties = nullptr,
PROJECT* aProject = nullptr );
PROJECT* aProject = nullptr,
PROGRESS_REPORTER* aProgressReporter = nullptr );
/**
* Write either a full \a aBoard to a storage file in a format that this implementation
@ -296,6 +298,8 @@ public:
* it to be optionally NULL.
* @param aProject is the optional #PROJECT object primarily used by third party
* importers.
* @param aProgressReporter an optional progress reporter
* @param aLineCount a line count (necessary if a progress reporter is supplied)
* @return the successfully loaded board, or the same one as \a aAppendToMe if aAppendToMe
* was not NULL, and caller owns it.
*
@ -304,7 +308,8 @@ public:
* possible.
*/
virtual BOARD* Load( const wxString& aFileName, BOARD* aAppendToMe,
const PROPERTIES* aProperties = nullptr, PROJECT* aProject = nullptr );
const PROPERTIES* aProperties = nullptr, PROJECT* aProject = nullptr,
PROGRESS_REPORTER* aProgressReporter = nullptr );
/**
* Return a container with the cached library footprints generated in the last call to

View File

@ -352,7 +352,8 @@ void CLIPBOARD_IO::Save( const wxString& aFileName, BOARD* aBoard,
BOARD* CLIPBOARD_IO::Load( const wxString& aFileName, BOARD* aAppendToMe,
const PROPERTIES* aProperties, PROJECT* aProject )
const PROPERTIES* aProperties, PROJECT* aProject,
PROGRESS_REPORTER* aProgressReporter )
{
std::string result;

View File

@ -59,7 +59,8 @@ public:
BOARD_ITEM* Parse();
BOARD* Load( const wxString& aFileName, BOARD* aAppendToMe,
const PROPERTIES* aProperties = nullptr, PROJECT* aProject = nullptr ) override;
const PROPERTIES* aProperties = nullptr, PROJECT* aProject = nullptr,
PROGRESS_REPORTER* aProgressReporter = nullptr ) override;
void SetBoard( BOARD* aBoard );

View File

@ -1164,9 +1164,10 @@ void PCB_PAINTER::draw( const PAD* aPad, int aLayer )
m_gal->DrawPolygon( outline );
}
else
{
m_gal->DrawPolygon( poly->Vertices() );
}
// Now add on a rounded margin (using segments) if the margin > 0
if( margin.x > 0 )

View File

@ -44,7 +44,7 @@ static void not_implemented( PLUGIN* aPlugin, const char* aCaller )
BOARD* PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe, const PROPERTIES* aProperties,
PROJECT* aProject )
PROJECT* aProject, PROGRESS_REPORTER* aProgressReporter )
{
not_implemented( this, __FUNCTION__ );
return nullptr;

View File

@ -64,7 +64,8 @@ const wxString ALTIUM_CIRCUIT_MAKER_PLUGIN::GetFileExtension() const
BOARD* ALTIUM_CIRCUIT_MAKER_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe,
const PROPERTIES* aProperties, PROJECT* aProject )
const PROPERTIES* aProperties, PROJECT* aProject,
PROGRESS_REPORTER* aProgressReporter )
{
m_props = aProperties;

View File

@ -39,7 +39,8 @@ public:
const wxString PluginName() const override;
BOARD* Load( const wxString& aFileName, BOARD* aAppendToMe, const PROPERTIES* aProperties,
PROJECT* aProject = nullptr ) override;
PROJECT* aProject = nullptr,
PROGRESS_REPORTER* aProgressReporter = nullptr ) override;
const wxString GetFileExtension() const override;

View File

@ -64,7 +64,8 @@ const wxString ALTIUM_CIRCUIT_STUDIO_PLUGIN::GetFileExtension() const
BOARD* ALTIUM_CIRCUIT_STUDIO_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe,
const PROPERTIES* aProperties, PROJECT* aProject )
const PROPERTIES* aProperties, PROJECT* aProject,
PROGRESS_REPORTER* aProgressReporter )
{
m_props = aProperties;

View File

@ -39,7 +39,7 @@ public:
const wxString PluginName() const override;
BOARD* Load( const wxString& aFileName, BOARD* aAppendToMe, const PROPERTIES* aProperties,
PROJECT* aProject ) override;
PROJECT* aProject, PROGRESS_REPORTER* aProgressReporter = nullptr ) override;
const wxString GetFileExtension() const override;

View File

@ -64,7 +64,8 @@ const wxString ALTIUM_DESIGNER_PLUGIN::GetFileExtension() const
BOARD* ALTIUM_DESIGNER_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe,
const PROPERTIES* aProperties, PROJECT* aProject )
const PROPERTIES* aProperties, PROJECT* aProject,
PROGRESS_REPORTER* aProgressReporter )
{
m_props = aProperties;

View File

@ -41,7 +41,8 @@ public:
const wxString PluginName() const override;
BOARD* Load( const wxString& aFileName, BOARD* aAppendToMe, const PROPERTIES* aProperties,
PROJECT* aProject = nullptr) override;
PROJECT* aProject = nullptr,
PROGRESS_REPORTER* aProgressReporter = nullptr ) override;
const wxString GetFileExtension() const override;

View File

@ -106,7 +106,8 @@ std::vector<FOOTPRINT*> CADSTAR_PCB_ARCHIVE_PLUGIN::GetImportedCachedLibraryFoot
BOARD* CADSTAR_PCB_ARCHIVE_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe,
const PROPERTIES* aProperties, PROJECT* aProject )
const PROPERTIES* aProperties, PROJECT* aProject,
PROGRESS_REPORTER* aProgressReporter )
{
m_props = aProperties;
m_board = aAppendToMe ? aAppendToMe : new BOARD();

View File

@ -39,7 +39,8 @@ public:
const wxString PluginName() const override;
BOARD* Load( const wxString& aFileName, BOARD* aAppendToMe,
const PROPERTIES* aProperties = nullptr, PROJECT* aProject = nullptr ) override;
const PROPERTIES* aProperties = nullptr, PROJECT* aProject = nullptr,
PROGRESS_REPORTER* aProgressReporter = nullptr ) override;
const wxString GetFileExtension() const override;

View File

@ -67,6 +67,7 @@ Load() TODO's
#include <properties.h>
#include <trigo.h>
#include <math/util.h> // for KiROUND
#include <widgets/progress_reporter.h>
#include <board.h>
#include <board_design_settings.h>
@ -207,12 +208,14 @@ static void setKeepoutSettingsToZone( ZONE* aZone, LAYER_NUM aLayer )
}
void ERULES::parse( wxXmlNode* aRules )
void ERULES::parse( wxXmlNode* aRules, std::function<void()> aCheckpoint )
{
wxXmlNode* child = aRules->GetChildren();
while( child )
{
aCheckpoint();
if( child->GetName() == "param" )
{
const wxString& name = child->GetAttribute( "name" );
@ -275,6 +278,10 @@ void ERULES::parse( wxXmlNode* aRules )
EAGLE_PLUGIN::EAGLE_PLUGIN() :
m_rules( new ERULES() ),
m_xpath( new XPATH() ),
m_progressReporter( nullptr ),
m_doneCount( 0 ),
m_lastProgressCount( 0 ),
m_totalCount( 0 ),
m_mod_time( wxDateTime::Now() )
{
using namespace std::placeholders;
@ -305,6 +312,26 @@ const wxString EAGLE_PLUGIN::GetFileExtension() const
return wxT( "brd" );
}
void EAGLE_PLUGIN::checkpoint()
{
const unsigned PROGRESS_DELTA = 50;
if( m_progressReporter )
{
if( ++m_doneCount > m_lastProgressCount + PROGRESS_DELTA )
{
m_progressReporter->SetCurrentProgress(( (double) m_doneCount ) / m_totalCount );
if( !m_progressReporter->KeepRefreshing() )
THROW_IO_ERROR( ( "Open cancelled by user." ) );
m_lastProgressCount = m_doneCount;
}
}
}
wxSize inline EAGLE_PLUGIN::kicad_fontz( const ECOORD& d, int aTextThickness ) const
{
// Eagle includes stroke thickness in the text size, KiCAD does not
@ -314,7 +341,8 @@ wxSize inline EAGLE_PLUGIN::kicad_fontz( const ECOORD& d, int aTextThickness ) c
BOARD* EAGLE_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe,
const PROPERTIES* aProperties, PROJECT* aProject )
const PROPERTIES* aProperties, PROJECT* aProject,
PROGRESS_REPORTER* aProgressReporter )
{
LOCALE_IO toggle; // toggles on, then off, the C locale.
wxXmlNode* doc;
@ -322,6 +350,7 @@ BOARD* EAGLE_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe,
init( aProperties );
m_board = aAppendToMe ? aAppendToMe : new BOARD();
m_progressReporter = aProgressReporter;
// Give the filename to the board if it's new
if( !aAppendToMe )
@ -332,6 +361,14 @@ BOARD* EAGLE_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe,
try
{
if( m_progressReporter )
{
m_progressReporter->Report( wxString::Format( _( "Loading %s..." ), aFileName ) );
if( !m_progressReporter->KeepRefreshing() )
THROW_IO_ERROR( ( "Open cancelled by user." ) );
}
wxFileName fn = aFileName;
// Load the document
wxFFileInputStream stream( fn.GetFullPath() );
@ -339,7 +376,7 @@ BOARD* EAGLE_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe,
if( !stream.IsOk() || !xmlDocument.Load( stream ) )
{
THROW_IO_ERROR( wxString::Format( _( "Unable to read file \"%s\"" ),
THROW_IO_ERROR( wxString::Format( _( "Unable to read file '%s'" ),
fn.GetFullPath() ) );
}
@ -414,9 +451,7 @@ std::vector<FOOTPRINT*> EAGLE_PLUGIN::GetImportedCachedLibraryFootprints()
std::vector<FOOTPRINT*> retval;
for( std::pair<wxString, FOOTPRINT*> fp : m_templates )
{
retval.push_back( static_cast<FOOTPRINT*>( fp.second->Clone() ) );
}
return retval;
}
@ -458,12 +493,53 @@ void EAGLE_PLUGIN::loadAllSections( wxXmlNode* aDoc )
wxXmlNode* board = drawingChildren["board"];
NODE_MAP boardChildren = MapChildren( board );
auto count_children = [this]( wxXmlNode* aNode )
{
if( aNode )
{
wxXmlNode* child = aNode->GetChildren();
while( child )
{
m_totalCount++;
child = child->GetNext();
}
}
};
wxXmlNode* designrules = boardChildren["designrules"];
wxXmlNode* layers = drawingChildren["layers"];
wxXmlNode* plain = boardChildren["plain"];
wxXmlNode* signals = boardChildren["signals"];
wxXmlNode* libs = boardChildren["libraries"];
wxXmlNode* elems = boardChildren["elements"];
if( m_progressReporter )
{
m_totalCount = 0;
m_doneCount = 0;
count_children( designrules );
count_children( layers );
count_children( plain );
count_children( signals );
count_children( elems );
while( libs )
{
count_children( MapChildren( libs )["packages"] );
libs = libs->GetNext();
}
// Rewind
libs = boardChildren["libraries"];
}
m_xpath->push( "eagle.drawing" );
{
m_xpath->push( "board" );
wxXmlNode* designrules = boardChildren["designrules"];
loadDesignRules( designrules );
m_xpath->pop();
@ -472,7 +548,6 @@ void EAGLE_PLUGIN::loadAllSections( wxXmlNode* aDoc )
{
m_xpath->push( "layers" );
wxXmlNode* layers = drawingChildren["layers"];
loadLayerDefs( layers );
mapEagleLayersToKicad();
@ -482,19 +557,12 @@ void EAGLE_PLUGIN::loadAllSections( wxXmlNode* aDoc )
{
m_xpath->push( "board" );
wxXmlNode* plain = boardChildren["plain"];
loadPlain( plain );
wxXmlNode* signals = boardChildren["signals"];
loadSignals( signals );
wxXmlNode* libs = boardChildren["libraries"];
loadLibraries( libs );
wxXmlNode* elems = boardChildren["elements"];
loadElements( elems );
m_xpath->pop(); // "board"
m_xpath->pop();
}
m_xpath->pop(); // "eagle.drawing"
@ -506,7 +574,7 @@ void EAGLE_PLUGIN::loadDesignRules( wxXmlNode* aDesignRules )
if( aDesignRules )
{
m_xpath->push( "designrules" );
m_rules->parse( aDesignRules );
m_rules->parse( aDesignRules, [this](){ checkpoint(); } );
m_xpath->pop(); // "designrules"
}
}
@ -533,9 +601,7 @@ void EAGLE_PLUGIN::loadLayerDefs( wxXmlNode* aLayers )
// find the subset of layers that are copper and active
if( elayer.number >= 1 && elayer.number <= 16 && ( !elayer.active || *elayer.active ) )
{
cu.push_back( elayer );
}
layerNode = layerNode->GetNext();
}
@ -546,9 +612,13 @@ void EAGLE_PLUGIN::loadLayerDefs( wxXmlNode* aLayers )
for( EITER it = cu.begin(); it != cu.end(); ++it, ++ki_layer_count )
{
if( ki_layer_count == 0 )
{
m_cu_map[it->number] = F_Cu;
}
else if( ki_layer_count == int( cu.size()-1 ) )
{
m_cu_map[it->number] = B_Cu;
}
else
{
// some eagle boards do not have contiguous layer number sequences.
@ -592,6 +662,8 @@ void EAGLE_PLUGIN::loadPlain( wxXmlNode* aGraphics )
// (polygon | wire | text | circle | rectangle | frame | hole)*
while( gr )
{
checkpoint();
wxString grName = gr->GetName();
if( grName == "wire" )
@ -945,6 +1017,8 @@ void EAGLE_PLUGIN::loadLibrary( wxXmlNode* aLib, const wxString* aLibName )
while( package )
{
checkpoint();
m_xpath->push( "package", "name" );
wxString pack_ref = package->GetAttribute( "name" );
@ -1018,6 +1092,8 @@ void EAGLE_PLUGIN::loadElements( wxXmlNode* aElements )
while( element )
{
checkpoint();
if( element->GetName() != "element" )
{
// Get next item
@ -1039,7 +1115,7 @@ void EAGLE_PLUGIN::loadElements( wxXmlNode* aElements )
if( it == m_templates.end() )
{
wxString emsg = wxString::Format( _( "No \"%s\" package in library \"%s\"" ),
wxString emsg = wxString::Format( _( "No '%s' package in library '%s'." ),
FROM_UTF8( e.package.c_str() ),
FROM_UTF8( e.library.c_str() ) );
THROW_IO_ERROR( emsg );
@ -1742,7 +1818,7 @@ void EAGLE_PLUGIN::packagePad( FOOTPRINT* aFootprint, wxXmlNode* aTree )
// if shape is not present, our default is circle and that matches their default "round"
}
if( e.diameter )
if( e.diameter && e.diameter->value > 0 )
{
int diameter = e.diameter->ToPcbUnits();
pad->SetSize( wxSize( diameter, diameter ) );
@ -2148,6 +2224,9 @@ void EAGLE_PLUGIN::packageHole( FOOTPRINT* aFootprint, wxXmlNode* aTree, bool aC
{
EHOLE e( aTree );
if( e.drill.value == 0 )
return;
// we add a PAD_ATTRIB::NPTH pad to this footprint.
PAD* pad = new PAD( aFootprint );
aFootprint->Add( pad );
@ -2188,7 +2267,7 @@ void EAGLE_PLUGIN::packageSMD( FOOTPRINT* aFootprint, wxXmlNode* aTree ) const
ESMD e( aTree );
PCB_LAYER_ID layer = kicad_layer( e.layer );
if( !IsCopperLayer( layer ) )
if( !IsCopperLayer( layer ) || e.dx.value == 0 || e.dy.value == 0 )
return;
PAD* pad = new PAD( aFootprint );
@ -2304,6 +2383,8 @@ void EAGLE_PLUGIN::loadSignals( wxXmlNode* aSignals )
while( net )
{
checkpoint();
bool sawPad = false;
zones.clear();
@ -2557,7 +2638,13 @@ void EAGLE_PLUGIN::mapEagleLayersToKicad()
inputDescs.push_back( layerDesc );
}
if( m_progressReporter && dynamic_cast<wxWindow*>( m_progressReporter ) )
dynamic_cast<wxWindow*>( m_progressReporter )->Hide();
m_layer_map = m_layer_mapping_handler( inputDescs );
if( m_progressReporter && dynamic_cast<wxWindow*>( m_progressReporter ))
dynamic_cast<wxWindow*>( m_progressReporter )->Show();
}
PCB_LAYER_ID EAGLE_PLUGIN::kicad_layer( int aEagleLayer ) const

View File

@ -78,7 +78,7 @@ struct ERULES
mdWireWire ( 0 )
{}
void parse( wxXmlNode* aRules );
void parse( wxXmlNode* aRules, std::function<void()> aCheckpoint );
///< percent over 100%. 0-> not elongated, 100->twice as wide as is tall
///< Goes into making a scaling factor for "long" pads.
@ -131,7 +131,8 @@ public:
const wxString PluginName() const override;
BOARD* Load( const wxString& aFileName, BOARD* aAppendToMe,
const PROPERTIES* aProperties = nullptr, PROJECT* aProject = nullptr ) override;
const PROPERTIES* aProperties = nullptr, PROJECT* aProject = nullptr,
PROGRESS_REPORTER* aProgressReporter = nullptr ) override;
std::vector<FOOTPRINT*> GetImportedCachedLibraryFootprints() override;
@ -178,6 +179,8 @@ private:
/// initialize PLUGIN like a constructor would, and futz with fresh BOARD if needed.
void init( const PROPERTIES* aProperties );
void checkpoint();
void clear_cu_map();
/// Convert an Eagle distance to a KiCad distance.
@ -299,6 +302,11 @@ private:
const PROPERTIES* m_props; ///< passed via Save() or Load(), no ownership, may be NULL.
BOARD* m_board; ///< which BOARD is being worked on, no ownership here
PROGRESS_REPORTER* m_progressReporter; ///< optional; may be nullptr
unsigned m_doneCount;
unsigned m_lastProgressCount;
unsigned m_totalCount; ///< for progress reporting
int m_min_trace; ///< smallest trace we find on Load(), in BIU.
int m_min_hole; ///< smallest diameter hole we find on Load(), in BIU.
int m_min_via; ///< smallest via we find on Load(), in BIU.

View File

@ -59,7 +59,8 @@ const wxString FABMASTER_PLUGIN::GetFileExtension() const
BOARD* FABMASTER_PLUGIN::Load( const wxString &aFileName, BOARD *aAppendToMe,
const PROPERTIES *aProperties, PROJECT *aProject )
const PROPERTIES *aProperties, PROJECT *aProject,
PROGRESS_REPORTER* aProgressReporter )
{
m_props = aProperties;

View File

@ -43,7 +43,9 @@ public:
BOARD* Load( const wxString& aFileName,
BOARD* aAppendToMe,
const PROPERTIES* aProperties = NULL, PROJECT* aProject = nullptr ) override;
const PROPERTIES* aProperties = NULL,
PROJECT* aProject = nullptr,
PROGRESS_REPORTER* aProgressReporter = nullptr ) override;
const wxString GetFileExtension() const override;

View File

@ -47,6 +47,7 @@
#include <plugins/kicad/pcb_parser.h>
#include <trace_helpers.h>
#include <pcb_track.h>
#include <widgets/progress_reporter.h>
#include <wildcards_and_files_ext.h>
#include <wx/dir.h>
#include <wx/log.h>
@ -2188,11 +2189,26 @@ PCB_IO::~PCB_IO()
BOARD* PCB_IO::Load( const wxString& aFileName, BOARD* aAppendToMe, const PROPERTIES* aProperties,
PROJECT* aProject )
PROJECT* aProject, PROGRESS_REPORTER* aProgressReporter )
{
FILE_LINE_READER reader( aFileName );
BOARD* board = DoLoad( reader, aAppendToMe, aProperties );
unsigned lineCount = 0;
if( aProgressReporter )
{
aProgressReporter->Report( wxString::Format( _( "Loading %s..." ), aFileName ) );
if( !aProgressReporter->KeepRefreshing() )
THROW_IO_ERROR( ( "Open cancelled by user." ) );
while( reader.ReadLine() )
lineCount++;
reader.Rewind();
}
BOARD* board = DoLoad( reader, aAppendToMe, aProperties, aProgressReporter, lineCount );
// Give the filename to the board if it's new
if( !aAppendToMe )
@ -2202,12 +2218,14 @@ BOARD* PCB_IO::Load( const wxString& aFileName, BOARD* aAppendToMe, const PROPER
}
BOARD* PCB_IO::DoLoad( LINE_READER& aReader, BOARD* aAppendToMe, const PROPERTIES* aProperties )
BOARD* PCB_IO::DoLoad( LINE_READER& aReader, BOARD* aAppendToMe, const PROPERTIES* aProperties,
PROGRESS_REPORTER* aProgressReporter, unsigned aLineCount)
{
init( aProperties );
m_parser->SetLineReader( &aReader );
m_parser->SetBoard( aAppendToMe );
m_parser->SetProgressReporter( aProgressReporter, &aReader, aLineCount );
BOARD* board;

View File

@ -153,9 +153,11 @@ public:
const PROPERTIES* aProperties = nullptr ) override;
BOARD* Load( const wxString& aFileName, BOARD* aAppendToMe,
const PROPERTIES* aProperties = nullptr, PROJECT* aProject = nullptr ) override;
const PROPERTIES* aProperties = nullptr, PROJECT* aProject = nullptr,
PROGRESS_REPORTER* aProgressReporter = nullptr ) override;
BOARD* DoLoad( LINE_READER& aReader, BOARD* aAppendToMe, const PROPERTIES* aProperties );
BOARD* DoLoad( LINE_READER& aReader, BOARD* aAppendToMe, const PROPERTIES* aProperties,
PROGRESS_REPORTER* aProgressReporter, unsigned aLineCount );
void FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aLibraryPath,
bool aBestEfforts, const PROPERTIES* aProperties = nullptr ) override;

View File

@ -28,13 +28,11 @@
*/
#include <cerrno>
#include <common.h>
#include <confirm.h>
#include <macros.h>
#include <title_block.h>
#include <trigo.h>
#include <advanced_config.h>
#include <board.h>
#include <board_design_settings.h>
#include <pcb_dimension.h>
@ -54,10 +52,10 @@
#include <zones.h>
#include <plugins/kicad/pcb_parser.h>
#include <convert_basic_shapes_to_polygon.h> // for RECT_CHAMFER_POSITIONS definition
#include <template_fieldnames.h>
#include <math/util.h> // KiROUND, Clamp
#include <kicad_string.h>
#include <wx/log.h>
#include <widgets/progress_reporter.h>
using namespace PCB_KEYS_T;
@ -107,6 +105,27 @@ void PCB_PARSER::init()
}
void PCB_PARSER::checkpoint()
{
const unsigned PROGRESS_DELTA = 250;
if( m_progressReporter )
{
unsigned curLine = m_lineReader->LineNumber();
if( curLine > m_lastProgressLine + PROGRESS_DELTA )
{
m_progressReporter->SetCurrentProgress( ( (double) curLine ) / m_lineCount );
if( !m_progressReporter->KeepRefreshing() )
THROW_IO_ERROR( ( "Open cancelled by user." ) );
m_lastProgressLine = curLine;
}
}
}
void PCB_PARSER::skipCurrent()
{
int curr_level = 0;
@ -588,6 +607,8 @@ BOARD* PCB_PARSER::parseBOARD_unchecked()
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
{
checkpoint();
if( token != T_LEFT )
Expecting( T_LEFT );

View File

@ -60,6 +60,7 @@ class PCB_VIA;
class ZONE;
class FP_3DMODEL;
struct LAYER;
class PROGRESS_REPORTER;
/**
@ -72,7 +73,11 @@ public:
PCB_PARSER( LINE_READER* aReader = nullptr ) :
PCB_LEXER( aReader ),
m_board( nullptr ),
m_resetKIIDs( false )
m_resetKIIDs( false ),
m_progressReporter( nullptr ),
m_lineReader( nullptr ),
m_lastProgressLine( 0 ),
m_lineCount( 0 )
{
init();
}
@ -101,6 +106,15 @@ public:
m_resetKIIDs = true;
}
void SetProgressReporter( PROGRESS_REPORTER* aProgressReporter, const LINE_READER* aLineReader,
unsigned aLineCount )
{
m_progressReporter = aProgressReporter;
m_lineReader = aLineReader;
m_lastProgressLine = 0;
m_lineCount = aLineCount;
}
BOARD_ITEM* Parse();
/**
@ -154,6 +168,8 @@ private:
*/
void init();
void checkpoint();
/**
* Create a mapping from the (short-lived) bug where layer names were translated.
*
@ -342,6 +358,11 @@ private:
bool m_showLegacyZoneWarning;
PROGRESS_REPORTER* m_progressReporter; ///< optional; may be nullptr
const LINE_READER* m_lineReader; ///< for progress reporting
unsigned m_lastProgressLine;
unsigned m_lineCount; ///< for progress reporting
// Group membership info refers to other Uuids in the file.
// We don't want to rely on group declarations being last in the file, so
// we store info about the group declarations here during parsing and then resolve

View File

@ -88,6 +88,7 @@
#include <trigo.h>
#include <confirm.h>
#include <math/util.h> // for KiROUND
#include <widgets/progress_reporter.h>
typedef LEGACY_PLUGIN::BIU BIU;
@ -194,6 +195,28 @@ static bool inline isSpace( int c ) { return strchr( delims, c ) != nullptr; }
#define MASK(x) (1<<(x))
void LEGACY_PLUGIN::checkpoint()
{
const unsigned PROGRESS_DELTA = 250;
if( m_progressReporter )
{
unsigned curLine = m_reader->LineNumber();
if( curLine > m_lastProgressLine + PROGRESS_DELTA )
{
m_progressReporter->SetCurrentProgress( ( (double) curLine ) / m_lineCount );
if( !m_progressReporter->KeepRefreshing() )
THROW_IO_ERROR( ( "Open cancelled by user." ) );
m_lastProgressLine = curLine;
}
}
}
//-----<BOARD Load Functions>---------------------------------------------------
/// C string compare test for a specific length of characters.
@ -378,7 +401,8 @@ static inline long hexParse( const char* next, const char** out = NULL )
BOARD* LEGACY_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe,
const PROPERTIES* aProperties, PROJECT* aProject )
const PROPERTIES* aProperties, PROJECT* aProject,
PROGRESS_REPORTER* aProgressReporter )
{
LOCALE_IO toggle; // toggles on, then off, the C locale.
@ -402,13 +426,30 @@ BOARD* LEGACY_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe,
FILE_LINE_READER reader( aFileName );
m_reader = &reader; // member function accessibility
m_reader = &reader;
m_progressReporter = aProgressReporter;
checkVersion();
if( m_progressReporter )
{
m_lineCount = 0;
m_progressReporter->Report( wxString::Format( _( "Loading %s..." ), aFileName ) );
if( !m_progressReporter->KeepRefreshing() )
THROW_IO_ERROR( ( "Open cancelled by user." ) );
while( reader.ReadLine() )
m_lineCount++;
reader.Rewind();
}
loadAllSections( bool( aAppendToMe ) );
(void)boardDeleter.release(); // give it up so we dont delete it on exit
m_progressReporter = nullptr;
return m_board;
}
@ -426,6 +467,8 @@ void LEGACY_PLUGIN::loadAllSections( bool doAppend )
while( ( line = READLINE( m_reader ) ) != NULL )
{
checkpoint();
// put the more frequent ones at the top, but realize TRACKs are loaded as a group
if( TESTLINE( "$MODULE" ) )
@ -2200,6 +2243,8 @@ void LEGACY_PLUGIN::loadTrackList( int aStructType )
while( ( line = READLINE( m_reader ) ) != NULL )
{
checkpoint();
// read two lines per loop iteration, each loop is one TRACK or VIA
// example first line:
// e.g. "Po 0 23994 28800 24400 28800 150 -1" for a track
@ -3386,6 +3431,9 @@ LEGACY_PLUGIN::LEGACY_PLUGIN() :
m_cu_count( 16 ), // for FootprintLoad()
m_board( nullptr ),
m_props( nullptr ),
m_progressReporter( nullptr ),
m_lastProgressLine( 0 ),
m_lineCount( 0 ),
m_reader( nullptr ),
m_fp( nullptr ),
m_cache( nullptr )

View File

@ -74,7 +74,8 @@ public:
}
BOARD* Load( const wxString& aFileName, BOARD* aAppendToMe,
const PROPERTIES* aProperties = nullptr, PROJECT* aProject = nullptr ) override;
const PROPERTIES* aProperties = nullptr, PROJECT* aProject = nullptr,
PROGRESS_REPORTER* aProgressReporter = nullptr ) override;
void FootprintEnumerate( wxArrayString& aFootprintNames, const wxString& aLibraryPath,
bool aBestEfforts,
@ -101,6 +102,11 @@ public:
static LSET leg_mask2new( int cu_count, unsigned aMask );
protected:
/// initialize PLUGIN like a constructor would, and futz with fresh BOARD if needed.
void init( const PROPERTIES* aProperties );
void checkpoint();
///< Converts net code using the mapping table if available,
///< otherwise returns unchanged net code
inline int getNetCode( int aNetCode )
@ -178,7 +184,11 @@ protected:
wxString m_error; ///< for throwing exceptions
BOARD* m_board; ///< which BOARD, no ownership here
const PROPERTIES* m_props; ///< passed via Save() or Load(), no ownership, may be NULL.
const PROPERTIES* m_props; ///< passed via Save() or Load(), no ownership,
///< may be NULL.
PROGRESS_REPORTER* m_progressReporter; ///< may be NULL, no ownership
unsigned m_lastProgressLine;
unsigned m_lineCount; ///< for progress reporting
LINE_READER* m_reader; ///< no ownership here.
FILE* m_fp; ///< no ownership here.
@ -190,9 +200,6 @@ protected:
std::vector<int> m_netCodes; ///< net codes mapping for boards being loaded
/// initialize PLUGIN like a constructor would, and futz with fresh BOARD if needed.
void init( const PROPERTIES* aProperties );
double biuToDisk; ///< convert from BIUs to disk engineering units
///< with this scale factor

View File

@ -66,7 +66,8 @@ const wxString PCAD_PLUGIN::GetFileExtension() const
BOARD* PCAD_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe,
const PROPERTIES* aProperties, PROJECT* aProject )
const PROPERTIES* aProperties, PROJECT* aProject,
PROGRESS_REPORTER* aProgressReporter )
{
wxXmlDocument xmlDoc;

View File

@ -43,7 +43,8 @@ public:
BOARD* Load( const wxString& aFileName,
BOARD* aAppendToMe,
const PROPERTIES* aProperties = nullptr,
PROJECT* aProject = nullptr ) override;
PROJECT* aProject = nullptr,
PROGRESS_REPORTER* aProgressReporter = nullptr ) override;
const wxString GetFileExtension() const override;

View File

@ -55,6 +55,7 @@
#include <view/view_controls.h>
#include <footprint_viewer_frame.h>
#include <footprint_edit_frame.h>
#include <widgets/progress_reporter.h>
using namespace std::placeholders;
@ -1018,8 +1019,10 @@ int PCB_CONTROL::AppendBoard( PLUGIN& pi, wxString& fileName )
props["page_width"] = xbuf;
props["page_height"] = ybuf;
WX_PROGRESS_REPORTER progressReporter( editFrame, _( "Loading PCB" ), 1 );
editFrame->GetDesignSettings().GetNetClasses().Clear();
pi.Load( fileName, brd, &props );
pi.Load( fileName, brd, &props, nullptr, &progressReporter );
}
catch( const IO_ERROR& ioe )
{