void DIALOG_SYMBOL_REMAP::remapSymbolsToLibTable( REPORTER& aReporter ) { wxString msg; SCH_SCREENS schematic; SCH_COMPONENT* symbol; SCH_ITEM* item; SCH_ITEM* nextItem; SCH_SCREEN* screen; for( screen = schematic.GetFirst(); screen; screen = schematic.GetNext() ) { for( item = screen->GetDrawItems(); item; item = nextItem ) { nextItem = item->Next(); if( item->Type() != SCH_COMPONENT_T ) continue; symbol = dynamic_cast< SCH_COMPONENT* >( item ); if( !remapSymbolToLibTable( symbol ) ) { msg.Printf( _( "No symbol \"%s\" found in symbol library table." ), symbol->GetLibId().GetLibItemName().wx_str() ); aReporter.Report( msg, REPORTER::RPT_WARNING ); } else { msg.Printf( _( "Symbol \"%s\" mapped to symbol library \"%s\"." ), symbol->GetLibId().GetLibItemName().wx_str(), symbol->GetLibId().GetLibNickname().wx_str() ); aReporter.Report( msg, REPORTER::RPT_ACTION ); screen->SetModify(); } } } aReporter.Report( _( "Symbol library table mapping complete!" ), REPORTER::RPT_INFO ); schematic.UpdateSymbolLinks( true ); }
bool DIALOG_SYMBOL_REMAP::backupProject( REPORTER& aReporter ) { static wxString backupFolder = "rescue-backup"; wxString tmp; wxString errorMsg; wxFileName srcFileName; wxFileName destFileName; wxFileName backupPath; SCH_SCREENS schematic; // Copy backup files to different folder so as not to pollute the project folder. destFileName.SetPath( Prj().GetProjectPath() ); destFileName.AppendDir( backupFolder ); backupPath = destFileName; if( !destFileName.DirExists() ) { if( !destFileName.Mkdir() ) { errorMsg.Printf( _( "Cannot create project remap back up folder \"%s\"." ), destFileName.GetPath() ); wxMessageDialog dlg( this, errorMsg, _( "Backup Error" ), wxYES_NO | wxCENTRE | wxRESIZE_BORDER | wxICON_QUESTION ); dlg.SetYesNoLabels( wxMessageDialog::ButtonLabel( _( "Continue with Rescue" ) ), wxMessageDialog::ButtonLabel( _( "Abort Rescue" ) ) ); if( dlg.ShowModal() == wxID_NO ) return false; } } // Time stamp to append to file name in case multiple remappings are performed. wxString timeStamp = wxDateTime::Now().Format( "-%Y-%m-%d-%H-%M-%S" ); // Back up symbol library table. srcFileName.SetPath( Prj().GetProjectPath() ); srcFileName.SetName( SYMBOL_LIB_TABLE::GetSymbolLibTableFileName() ); destFileName = srcFileName; destFileName.AppendDir( backupFolder ); destFileName.SetName( destFileName.GetName() + timeStamp ); tmp.Printf( _( "Backing up file \"%s\" to file \"%s\"." ), srcFileName.GetFullPath(), destFileName.GetFullPath() ); aReporter.Report( tmp, REPORTER::RPT_INFO ); if( wxFileName::Exists( srcFileName.GetFullPath() ) && !wxCopyFile( srcFileName.GetFullPath(), destFileName.GetFullPath() ) ) { tmp.Printf( _( "Failed to back up file \"%s\".\n" ), srcFileName.GetFullPath() ); errorMsg += tmp; } // Back up the schematic files. for( SCH_SCREEN* screen = schematic.GetFirst(); screen; screen = schematic.GetNext() ) { destFileName = screen->GetFileName(); destFileName.SetName( destFileName.GetName() + timeStamp ); // Check for nest hierarchical schematic paths. if( destFileName.GetPath() != backupPath.GetPath() ) { destFileName.SetPath( backupPath.GetPath() ); wxArrayString srcDirs = wxFileName( screen->GetFileName() ).GetDirs(); wxArrayString destDirs = wxFileName( Prj().GetProjectPath() ).GetDirs(); for( size_t i = destDirs.GetCount(); i < srcDirs.GetCount(); i++ ) destFileName.AppendDir( srcDirs[i] ); } else { destFileName.AppendDir( backupFolder ); } tmp.Printf( _( "Backing up file \"%s\" to file \"%s\"." ), screen->GetFileName(), destFileName.GetFullPath() ); aReporter.Report( tmp, REPORTER::RPT_INFO ); if( !destFileName.DirExists() && !destFileName.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) ) { tmp.Printf( _( "Failed to create backup folder \"%s\"\n" ), destFileName.GetPath() ); errorMsg += tmp; continue; } if( wxFileName::Exists( screen->GetFileName() ) && !wxCopyFile( screen->GetFileName(), destFileName.GetFullPath() ) ) { tmp.Printf( _( "Failed to back up file \"%s\".\n" ), screen->GetFileName() ); errorMsg += tmp; } } // Back up the project file. destFileName = Prj().GetProjectFullName(); destFileName.SetName( destFileName.GetName() + timeStamp ); destFileName.AppendDir( backupFolder ); tmp.Printf( _( "Backing up file \"%s\" to file \"%s\"." ), Prj().GetProjectFullName(), destFileName.GetFullPath() ); aReporter.Report( tmp, REPORTER::RPT_INFO ); if( wxFileName::Exists( Prj().GetProjectFullName() ) && !wxCopyFile( Prj().GetProjectFullName(), destFileName.GetFullPath() ) ) { tmp.Printf( _( "Failed to back up file \"%s\".\n" ), Prj().GetProjectFullName() ); errorMsg += tmp; } // Back up the cache library. srcFileName.SetPath( Prj().GetProjectPath() ); srcFileName.SetName( Prj().GetProjectName() + "-cache" ); srcFileName.SetExt( SchematicLibraryFileExtension ); destFileName = srcFileName; destFileName.SetName( destFileName.GetName() + timeStamp ); destFileName.AppendDir( backupFolder ); tmp.Printf( _( "Backing up file \"%s\" to file \"%s\"." ), srcFileName.GetFullPath(), destFileName.GetFullPath() ); aReporter.Report( tmp, REPORTER::RPT_INFO ); if( srcFileName.Exists() && !wxCopyFile( srcFileName.GetFullPath(), destFileName.GetFullPath() ) ) { tmp.Printf( _( "Failed to back up file \"%s\".\n" ), srcFileName.GetFullPath() ); errorMsg += tmp; } // Back up the rescue symbol library if it exists. srcFileName.SetName( Prj().GetProjectName() + "-rescue" ); destFileName.SetName( srcFileName.GetName() + timeStamp ); tmp.Printf( _( "Backing up file \"%s\" to file \"%s\"." ), srcFileName.GetFullPath(), destFileName.GetFullPath() ); aReporter.Report( tmp, REPORTER::RPT_INFO ); if( srcFileName.Exists() && !wxCopyFile( srcFileName.GetFullPath(), destFileName.GetFullPath() ) ) { tmp.Printf( _( "Failed to back up file \"%s\".\n" ), srcFileName.GetFullPath() ); errorMsg += tmp; } // Back up the rescue symbol library document file if it exists. srcFileName.SetExt( "dcm" ); destFileName.SetExt( srcFileName.GetExt() ); tmp.Printf( _( "Backing up file \"%s\" to file \"%s\"." ), srcFileName.GetFullPath(), destFileName.GetFullPath() ); aReporter.Report( tmp, REPORTER::RPT_INFO ); if( srcFileName.Exists() && !wxCopyFile( srcFileName.GetFullPath(), destFileName.GetFullPath() ) ) { tmp.Printf( _( "Failed to back up file \"%s\".\n" ), srcFileName.GetFullPath() ); errorMsg += tmp; } if( !errorMsg.IsEmpty() ) { wxMessageDialog dlg( this, _( "Some of the project files could not be backed up." ), _( "Backup Error" ), wxYES_NO | wxCENTRE | wxRESIZE_BORDER | wxICON_QUESTION ); errorMsg.Trim(); dlg.SetExtendedMessage( errorMsg ); dlg.SetYesNoLabels( wxMessageDialog::ButtonLabel( _( "Continue with Rescue" ) ), wxMessageDialog::ButtonLabel( _( "Abort Rescue" ) ) ); if( dlg.ShowModal() == wxID_NO ) return false; } return true; }
void DIALOG_SYMBOL_REMAP::createProjectSymbolLibTable( REPORTER& aReporter ) { wxString msg; std::vector< PART_LIB* > libs; if( getLibsNotInGlobalSymbolLibTable( libs ) ) { SYMBOL_LIB_TABLE prjLibTable; std::vector< wxString > libNames = SYMBOL_LIB_TABLE::GetGlobalLibTable().GetLogicalLibs(); for( auto lib : libs ) { wxString libName = lib->GetName(); int libNameInc = 1; int libNameLen = libName.Length(); // Spaces in the file name will break the symbol name because they are not // quoted in the symbol library file format. libName.Replace( " ", "-" ); // Don't create duplicate table entries. while( std::find( libNames.begin(), libNames.end(), libName ) != libNames.end() ) { libName = libName.Left( libNameLen ); libName << libNameInc; libNameInc++; } wxString pluginType = SCH_IO_MGR::ShowType( SCH_IO_MGR::SCH_LEGACY ); wxFileName fn = lib->GetFullFileName(); // Use environment variable substitution where possible. This is based solely // on the internal user environment variable list. Checking against all of the // system wide environment variables is probably not a good idea. wxString fullFileName = NormalizePath( fn, &Pgm().GetLocalEnvVariables(), &Prj() ); // Fall back to the absolute library path. if( fullFileName.IsEmpty() ) fullFileName = lib->GetFullFileName(); wxFileName tmpFn = fullFileName; // Don't add symbol libraries that do not exist. if( tmpFn.Normalize() && tmpFn.FileExists() ) { msg.Printf( _( "Adding library \"%s\", file \"%s\" to project symbol library table." ), libName, fullFileName ); aReporter.Report( msg, REPORTER::RPT_INFO ); prjLibTable.InsertRow( new SYMBOL_LIB_TABLE_ROW( libName, fullFileName, pluginType ) ); } else { msg.Printf( _( "Library \"%s\" not found." ), fullFileName ); aReporter.Report( msg, REPORTER::RPT_WARNING ); } } // Don't save empty project symbol library table. if( !prjLibTable.IsEmpty() ) { wxFileName fn( Prj().GetProjectPath(), SYMBOL_LIB_TABLE::GetSymbolLibTableFileName() ); try { FILE_OUTPUTFORMATTER formatter( fn.GetFullPath() ); prjLibTable.Format( &formatter, 0 ); } catch( const IO_ERROR& ioe ) { msg.Printf( _( "Failed to write project symbol library table. Error:\n %s" ), ioe.What() ); aReporter.ReportTail( msg, REPORTER::RPT_ERROR ); } aReporter.ReportTail( _( "Created project symbol library table.\n" ), REPORTER::RPT_INFO ); } } }
int SCH_REFERENCE_LIST::CheckAnnotation( REPORTER& aReporter ) { int error = 0; wxString tmp; wxString msg; SortByRefAndValue(); // Spiit reference designators into name (prefix) and number: IC1 becomes IC, and 1. SplitReferences(); // count not yet annotated items or annotation error. for( unsigned ii = 0; ii < componentFlatList.size(); ii++ ) { msg.Empty(); tmp.Empty(); if( componentFlatList[ii].m_IsNew ) // Not yet annotated { if( componentFlatList[ii].m_NumRef >= 0 ) tmp << componentFlatList[ii].m_NumRef; else tmp = wxT( "?" ); if( ( componentFlatList[ii].m_Unit > 0 ) && ( componentFlatList[ii].m_Unit < 0x7FFFFFFF ) ) { msg.Printf( _( "Item not annotated: %s%s (unit %d)\n" ), GetChars( componentFlatList[ii].GetRef() ), GetChars( tmp ), componentFlatList[ii].m_Unit ); } else { msg.Printf( _( "Item not annotated: %s%s\n" ), GetChars( componentFlatList[ii].GetRef() ), GetChars( tmp ) ); } aReporter.Report( msg, REPORTER::RPT_WARNING ); error++; break; } // Error if unit number selected does not exist ( greater than the number of // parts in the component ). This can happen if a component has changed in a // library after a previous annotation. if( std::max( componentFlatList[ii].GetLibPart()->GetUnitCount(), 1 ) < componentFlatList[ii].m_Unit ) { if( componentFlatList[ii].m_NumRef >= 0 ) tmp << componentFlatList[ii].m_NumRef; else tmp = wxT( "?" ); msg.Printf( _( "Error: symbol %s%s unit %d and symbol has only %d units defined\n" ), GetChars( componentFlatList[ii].GetRef() ), GetChars( tmp ), componentFlatList[ii].m_Unit, componentFlatList[ii].GetLibPart()->GetUnitCount() ); aReporter.Report( msg, REPORTER::RPT_ERROR ); error++; break; } } if( error ) return error; // count the duplicated elements (if all are annotated) int imax = componentFlatList.size() - 1; for( int ii = 0; (ii < imax) && (error < 4); ii++ ) { msg.Empty(); tmp.Empty(); if( ( componentFlatList[ii].CompareRef( componentFlatList[ii + 1] ) != 0 ) || ( componentFlatList[ii].m_NumRef != componentFlatList[ii + 1].m_NumRef ) ) continue; // Same reference found. If same unit, error! if( componentFlatList[ii].m_Unit == componentFlatList[ii + 1].m_Unit ) { if( componentFlatList[ii].m_NumRef >= 0 ) tmp << componentFlatList[ii].m_NumRef; else tmp = wxT( "?" ); if( ( componentFlatList[ii].m_Unit > 0 ) && ( componentFlatList[ii].m_Unit < 0x7FFFFFFF ) ) { msg.Printf( _( "Multiple item %s%s (unit %d)\n" ), GetChars( componentFlatList[ii].GetRef() ), GetChars( tmp ), componentFlatList[ii].m_Unit ); } else { msg.Printf( _( "Multiple item %s%s\n" ), GetChars( componentFlatList[ii].GetRef() ), GetChars( tmp ) ); } aReporter.Report( msg, REPORTER::RPT_ERROR ); error++; continue; } /* Test error if units are different but number of parts per package * too high (ex U3 ( 1 part) and we find U3B this is an error) */ if( componentFlatList[ii].GetLibPart()->GetUnitCount() != componentFlatList[ii + 1].GetLibPart()->GetUnitCount() ) { if( componentFlatList[ii].m_NumRef >= 0 ) tmp << componentFlatList[ii].m_NumRef; else tmp = wxT( "?" ); if( ( componentFlatList[ii].m_Unit > 0 ) && ( componentFlatList[ii].m_Unit < 0x7FFFFFFF ) ) { msg.Printf( _( "Multiple item %s%s (unit %d)\n" ), GetChars( componentFlatList[ii].GetRef() ), GetChars( tmp ), componentFlatList[ii].m_Unit ); } else { msg.Printf( _( "Multiple item %s%s\n" ), GetChars( componentFlatList[ii].GetRef() ), GetChars( tmp ) ); } aReporter.Report( msg, REPORTER::RPT_ERROR ); error++; } // Error if values are different between units, for the same reference int next = ii + 1; if( componentFlatList[ii].CompareValue( componentFlatList[next] ) != 0 ) { msg.Printf( _( "Different values for %s%d%s (%s) and %s%d%s (%s)" ), GetChars( componentFlatList[ii].GetRef() ), componentFlatList[ii].m_NumRef, GetChars( LIB_PART::SubReference( componentFlatList[ii].m_Unit ) ), GetChars( componentFlatList[ii].m_Value->GetText() ), GetChars( componentFlatList[next].GetRef() ), componentFlatList[next].m_NumRef, GetChars( LIB_PART::SubReference( componentFlatList[next].m_Unit ) ), GetChars( componentFlatList[next].m_Value->GetText() ) ); aReporter.Report( msg, REPORTER::RPT_ERROR ); error++; } } // count the duplicated time stamps SortByTimeStamp(); for( int ii = 0; ( ii < imax ) && ( error < 4 ); ii++ ) { if( ( componentFlatList[ii].m_TimeStamp != componentFlatList[ii + 1].m_TimeStamp ) || ( componentFlatList[ii].GetSheetPath() != componentFlatList[ii + 1].GetSheetPath() ) ) continue; // Same time stamp found. wxString full_path; full_path.Printf( wxT( "%s%8.8X" ), GetChars( componentFlatList[ii].GetSheetPath().Path() ), componentFlatList[ii].m_TimeStamp ); msg.Printf( _( "Duplicate time stamp (%s) for %s%d and %s%d" ), GetChars( full_path ), GetChars( componentFlatList[ii].GetRef() ), componentFlatList[ii].m_NumRef, GetChars( componentFlatList[ii + 1].GetRef() ), componentFlatList[ii + 1].m_NumRef ); aReporter.Report( msg, REPORTER::RPT_WARNING ); error++; } return error; }
bool DIALOG_GEN_MODULE_POSITION::CreateFiles() { BOARD * brd = m_parent->GetBoard(); wxFileName fn; wxString msg; bool singleFile = OneFileOnly(); int fullcount = 0; // Count the footprints to place, do not yet create a file int fpcount = m_parent->DoGenFootprintsPositionFile( wxEmptyString, UnitsMM(), ForceAllSmd(), 2 ); if( fpcount == 0) { wxMessageBox( _( "No modules for automated placement." ) ); return false; } // Create output directory if it does not exist (also transform it in // absolute form). Bail if it fails wxFileName outputDir = wxFileName::DirName( m_plotOpts.GetOutputDirectory() ); wxString boardFilename = m_parent->GetBoard()->GetFileName(); m_reporter = &m_messagesPanel->Reporter(); if( !EnsureFileDirectoryExists( &outputDir, boardFilename, m_reporter ) ) { msg.Printf( _( "Could not write plot files to folder \"%s\"." ), GetChars( outputDir.GetPath() ) ); DisplayError( this, msg ); return false; } fn = m_parent->GetBoard()->GetFileName(); fn.SetPath( outputDir.GetPath() ); // Create the the Front or Top side placement file, // or the single file int side = 1; if( singleFile ) { side = 2; fn.SetName( fn.GetName() + wxT( "-" ) + wxT("all") ); } else fn.SetName( fn.GetName() + wxT( "-" ) + frontSideName ); fn.SetExt( FootprintPlaceFileExtension ); fpcount = m_parent->DoGenFootprintsPositionFile( fn.GetFullPath(), UnitsMM(), ForceAllSmd(), side ); if( fpcount < 0 ) { msg.Printf( _( "Unable to create '%s'." ), GetChars( fn.GetFullPath() ) ); wxMessageBox( msg ); m_reporter->Report( msg, REPORTER::RPT_ERROR ); return false; } if( singleFile ) msg.Printf( _( "Place file: '%s'." ), GetChars( fn.GetFullPath() ) ); else msg.Printf( _( "Front side (top side) place file: '%s'." ), GetChars( fn.GetFullPath() ) ); m_reporter->Report( msg, REPORTER::RPT_INFO ); msg.Printf( _( "Component count: %d." ), fpcount ); m_reporter->Report( msg, REPORTER::RPT_INFO ); if( singleFile ) { m_reporter->Report( _( "Componment Placement File generation OK." ), REPORTER::RPT_ACTION ); return true; } // Create the Back or Bottom side placement file fullcount = fpcount; side = 0; fn = brd->GetFileName(); fn.SetPath( outputDir.GetPath() ); fn.SetName( fn.GetName() + wxT( "-" ) + backSideName ); fn.SetExt( wxT( "pos" ) ); fpcount = m_parent->DoGenFootprintsPositionFile( fn.GetFullPath(), UnitsMM(), ForceAllSmd(), side ); if( fpcount < 0 ) { msg.Printf( _( "Unable to create file '%s'." ), GetChars( fn.GetFullPath() ) ); m_reporter->Report( msg, REPORTER::RPT_ERROR ); wxMessageBox( msg ); return false; } // Display results if( !singleFile ) { msg.Printf( _( "Back side (bottom side) place file: '%s'." ), GetChars( fn.GetFullPath() ) ); m_reporter->Report( msg, REPORTER::RPT_INFO ); msg.Printf( _( "Component count: %d." ), fpcount ); m_reporter->Report( msg, REPORTER::RPT_INFO ); } if( !singleFile ) { fullcount += fpcount; msg.Printf( _( "Full component count: %d\n" ), fullcount ); m_reporter->Report( msg, REPORTER::RPT_INFO ); } m_reporter->Report( _( "Componment Placement File generation OK." ), REPORTER::RPT_ACTION ); return true; }
void SCH_EDIT_FRAME::AnnotateComponents( bool aAnnotateSchematic, ANNOTATE_ORDER_T aSortOption, ANNOTATE_OPTION_T aAlgoOption, int aStartNumber, bool aResetAnnotation, bool aRepairTimestamps, bool aLockUnits, REPORTER& aReporter ) { SCH_REFERENCE_LIST references; SCH_SCREENS screens; // Build the sheet list. SCH_SHEET_LIST sheets( g_RootSheet ); // Map of locked components SCH_MULTI_UNIT_REFERENCE_MAP lockedComponents; // Map of previous annotation for building info messages std::map<timestamp_t, wxString> previousAnnotation; // Test for and replace duplicate time stamps in components and sheets. Duplicate // time stamps can happen with old schematics, schematic conversions, or manual // editing of files. if( aRepairTimestamps ) { int count = screens.ReplaceDuplicateTimeStamps(); if( count ) { wxString msg; msg.Printf( _( "%d duplicate time stamps were found and replaced." ), count ); aReporter.ReportTail( msg, REPORTER::RPT_WARNING ); } } // If units must be locked, collect all the sets that must be annotated together. if( aLockUnits ) { if( aAnnotateSchematic ) { sheets.GetMultiUnitComponents( lockedComponents ); } else { m_CurrentSheet->GetMultiUnitComponents( lockedComponents ); } } // Store previous annotations for building info messages mapExistingAnnotation( previousAnnotation ); // If it is an annotation for all the components, reset previous annotation. if( aResetAnnotation ) DeleteAnnotation( !aAnnotateSchematic ); // Set sheet number and number of sheets. SetSheetNumberAndCount(); // Build component list if( aAnnotateSchematic ) { sheets.GetComponents( references ); } else { m_CurrentSheet->GetComponents( references ); } // Break full components reference in name (prefix) and number: // example: IC1 become IC, and 1 references.SplitReferences(); switch( aSortOption ) { default: case SORT_BY_X_POSITION: references.SortByXCoordinate(); break; case SORT_BY_Y_POSITION: references.SortByYCoordinate(); break; } bool useSheetNum = false; int idStep = 100; switch( aAlgoOption ) { default: case INCREMENTAL_BY_REF: break; case SHEET_NUMBER_X_100: useSheetNum = true; break; case SHEET_NUMBER_X_1000: useSheetNum = true; idStep = 1000; break; } // Recalculate and update reference numbers in schematic references.Annotate( useSheetNum, idStep, aStartNumber, lockedComponents ); references.UpdateAnnotation(); for( size_t i = 0; i < references.GetCount(); i++ ) { SCH_COMPONENT* comp = references[ i ].GetComp(); wxString prevRef = previousAnnotation[ comp->GetTimeStamp() ]; wxString newRef = comp->GetField( REFERENCE )->GetFullyQualifiedText(); wxString msg; if( prevRef.Length() ) { if( newRef == prevRef ) continue; if( comp->GetUnitCount() > 1 ) msg.Printf( _( "Updated %s (unit %s) from %s to %s" ), GetChars( comp->GetField( VALUE )->GetShownText() ), LIB_PART::SubReference( comp->GetUnit(), false ), GetChars( prevRef ), GetChars( newRef ) ); else msg.Printf( _( "Updated %s from %s to %s" ), GetChars( comp->GetField( VALUE )->GetShownText() ), GetChars( prevRef ), GetChars( newRef ) ); } else { if( comp->GetUnitCount() > 1 ) msg.Printf( _( "Annotated %s (unit %s) as %s" ), GetChars( comp->GetField( VALUE )->GetShownText() ), LIB_PART::SubReference( comp->GetUnit(), false ), GetChars( newRef ) ); else msg.Printf( _( "Annotated %s as %s" ), GetChars( comp->GetField( VALUE )->GetShownText() ), GetChars( newRef ) ); } aReporter.Report( msg, REPORTER::RPT_ACTION ); } // Final control (just in case ... ). if( !CheckAnnotate( aReporter, !aAnnotateSchematic ) ) aReporter.ReportTail( _( "Annotation complete." ), REPORTER::RPT_ACTION ); // Update on screen references, that can be modified by previous calculations: m_CurrentSheet->UpdateAllScreenReferences(); SetSheetNumberAndCount(); SyncView(); GetCanvas()->Refresh(); OnModify(); }