void KICAD_MANAGER_FRAME::OnCloseWindow( wxCloseEvent& Event ) { int px, py; UpdateFileHistory( m_ProjectFileName.GetFullPath() ); if( !IsIconized() ) // save main frame position and size { GetPosition( &px, &py ); m_FramePos.x = px; m_FramePos.y = py; GetSize( &px, &py ); m_FrameSize.x = px; m_FrameSize.y = py; } Event.SetCanVeto( true ); // Close the help frame if( wxGetApp().GetHtmlHelpController() ) { if( wxGetApp().GetHtmlHelpController()->GetFrame() ) // returns NULL if no help frame active wxGetApp().GetHtmlHelpController()->GetFrame()->Close( true ); wxGetApp().SetHtmlHelpController( NULL ); } m_LeftWin->Show( false ); Destroy(); }
void KICAD_MANAGER_FRAME::OnCloseWindow( wxCloseEvent& Event ) { if( Kiway.PlayersClose( false ) ) { int px, py; UpdateFileHistory( GetProjectFileName(), &Pgm().GetFileHistory() ); if( !IsIconized() ) // save main frame position and size { GetPosition( &px, &py ); m_FramePos.x = px; m_FramePos.y = py; GetSize( &px, &py ); m_FrameSize.x = px; m_FrameSize.y = py; } Event.SetCanVeto( true ); m_LeftWin->Show( false ); Destroy(); } }
/* Loads a .kicad_wks page layout descr file */ bool PL_EDITOR_FRAME::LoadPageLayoutDescrFile( const wxString& aFullFileName ) { if( wxFileExists( aFullFileName ) ) { WORKSHEET_LAYOUT::GetTheInstance().SetPageLayout( aFullFileName ); SetCurrFileName( aFullFileName ); UpdateFileHistory( aFullFileName ); GetScreen()->ClrModify(); return true; } return false; }
void KICAD_MANAGER_FRAME::LoadProject( const wxFileName& aProjectFileName ) { // The project file should be valid by the time we get here or something has gone wrong. if( !aProjectFileName.Exists() ) return; // Any open KIFACE's must be closed if they are not part of the new project. // (We never want a KIWAY_PLAYER open on a KIWAY that isn't in the same project.) // User is prompted here to close those KIWAY_PLAYERs: if( !Kiway().PlayersClose( false ) ) return; SetTitle( wxString( "KiCad " ) + GetBuildVersion() ); // Save the project file for the currently loaded project. if( m_active_project ) Prj().ConfigLoad( PgmTop().SysSearch(), GeneralGroupName, s_KicadManagerParams ); m_active_project = true; ClearMsg(); SetProjectFileName( aProjectFileName.GetFullPath() ); Prj().ConfigLoad( PgmTop().SysSearch(), GeneralGroupName, s_KicadManagerParams ); wxString title = GetTitle() + " " + aProjectFileName.GetFullPath(); if( !aProjectFileName.IsDirWritable() ) title += _( " [Read Only]" ); else SetMruPath( Prj().GetProjectPath() ); // Only set MRU path if we have write access. Why? SetTitle( title ); UpdateFileHistory( aProjectFileName.GetFullPath(), &PgmTop().GetFileHistory() ); m_LeftWin->ReCreateTreePrj(); // Rebuild the list of watched paths. // however this is possible only when the main loop event handler is running, // so we use it to run the rebuild function. wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED, ID_INIT_WATCHED_PATHS ); wxPostEvent( this, cmd ); PrintPrjInfo(); }
bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool aCreateBackupFile ) { // please, keep it simple. prompting goes elsewhere. wxFileName pcbFileName = aFileName; if( pcbFileName.GetExt() == LegacyPcbFileExtension ) pcbFileName.SetExt( KiCadPcbFileExtension ); if( !IsWritable( pcbFileName ) ) { wxString msg = wxString::Format( _( "No access rights to write to file \"%s\"" ), GetChars( pcbFileName.GetFullPath() ) ); DisplayError( this, msg ); return false; } wxString backupFileName; if( aCreateBackupFile ) { backupFileName = createBackupFile( aFileName ); } GetBoard()->SynchronizeNetsAndNetClasses(); // Select default Netclass before writing file. // Useful to save default values in headers SetCurrentNetClass( NETCLASS::Default ); ClearMsgPanel(); wxString upperTxt; wxString lowerTxt; try { PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::KICAD_SEXP ) ); wxASSERT( pcbFileName.IsAbsolute() ); pi->Save( pcbFileName.GetFullPath(), GetBoard(), NULL ); } catch( const IO_ERROR& ioe ) { wxString msg = wxString::Format( _( "Error saving board file \"%s\".\n%s" ), GetChars( pcbFileName.GetFullPath() ), GetChars( ioe.What() ) ); DisplayError( this, msg ); lowerTxt.Printf( _( "Failed to create \"%s\"" ), GetChars( pcbFileName.GetFullPath() ) ); AppendMsgPanel( upperTxt, lowerTxt, CYAN ); return false; } GetBoard()->SetFileName( pcbFileName.GetFullPath() ); UpdateTitle(); // Put the saved file in File History, unless aCreateBackupFile // is false. // aCreateBackupFile == false is mainly used to write autosave files // and not need to have an autosave file in file history if( aCreateBackupFile ) UpdateFileHistory( GetBoard()->GetFileName() ); // Delete auto save file on successful save. wxFileName autoSaveFileName = pcbFileName; autoSaveFileName.SetName( GetAutoSaveFilePrefix() + pcbFileName.GetName() ); if( autoSaveFileName.FileExists() ) wxRemoveFile( autoSaveFileName.GetFullPath() ); if( !!backupFileName ) upperTxt.Printf( _( "Backup file: \"%s\"" ), GetChars( backupFileName ) ); lowerTxt.Printf( _( "Wrote board file: \"%s\"" ), GetChars( pcbFileName.GetFullPath() ) ); AppendMsgPanel( upperTxt, lowerTxt, CYAN ); GetScreen()->ClrModify(); GetScreen()->ClrSave(); return true; }
bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl ) { // This is for python: if( aFileSet.size() != 1 ) { UTF8 msg = StrPrintf( "Pcbnew:%s() takes only a single filename", __func__ ); DisplayError( this, msg ); return false; } wxString fullFileName( aFileSet[0] ); // We insist on caller sending us an absolute path, if it does not, we say it's a bug. wxASSERT_MSG( wxFileName( fullFileName ).IsAbsolute(), wxT( "Path is not absolute!" ) ); std::unique_ptr<wxSingleInstanceChecker> lockFile = ::LockFile( fullFileName ); if( !lockFile ) { wxString msg = wxString::Format( _( "PCB file \"%s\" is already open." ), fullFileName ); DisplayError( this, msg ); return false; } if( GetScreen()->IsModify() && !GetBoard()->IsEmpty() ) { if( !HandleUnsavedChanges( this, _( "The current PCB has been modified. Save changes?" ), [&]()->bool { return SavePcbFile( GetBoard()->GetFileName(), CREATE_BACKUP_FILE ); } ) ) { return false; } } // Release the lock file, until the new file is actually loaded ReleaseFile(); wxFileName pro = fullFileName; pro.SetExt( ProjectFileExtension ); bool is_new = !wxFileName::IsFileReadable( fullFileName ); // If its a non-existent schematic and caller thinks it exists if( is_new && !( aCtl & KICTL_CREATE ) ) { // notify user that fullFileName does not exist, ask if user wants to create it. wxString ask = wxString::Format( _( "PCB \"%s\" does not exist. Do you wish to create it?" ), fullFileName ); if( !IsOK( this, ask ) ) return false; } Clear_Pcb( false ); // pass false since we prompted above for a modified board IO_MGR::PCB_FILE_T pluginType = plugin_type( fullFileName, aCtl ); bool converted = pluginType != IO_MGR::LEGACY && pluginType != IO_MGR::KICAD_SEXP; if( !converted ) { // PROJECT::SetProjectFullName() is an impactful function. It should only be // called under carefully considered circumstances. // The calling code should know not to ask me here to change projects unless // it knows what consequences that will have on other KIFACEs running and using // this same PROJECT. It can be very harmful if that calling code is stupid. Prj().SetProjectFullName( pro.GetFullPath() ); // load project settings before BOARD LoadProjectSettings(); } if( is_new ) { OnModify(); } else { BOARD* loadedBoard = 0; // it will be set to non-NULL if loaded OK PLUGIN::RELEASER pi( IO_MGR::PluginFind( pluginType ) ); // This will rename the file if there is an autosave and the user want to recover CheckForAutoSaveFile( fullFileName ); try { PROPERTIES props; char xbuf[30]; char ybuf[30]; // EAGLE_PLUGIN can use this info to center the BOARD, but it does not yet. sprintf( xbuf, "%d", GetPageSizeIU().x ); sprintf( ybuf, "%d", GetPageSizeIU().y ); props["page_width"] = xbuf; props["page_height"] = ybuf; #if USE_INSTRUMENTATION // measure the time to load a BOARD. unsigned startTime = GetRunningMicroSecs(); #endif loadedBoard = pi->Load( fullFileName, NULL, &props ); #if USE_INSTRUMENTATION unsigned stopTime = GetRunningMicroSecs(); printf( "PLUGIN::Load(): %u usecs\n", stopTime - startTime ); #endif } catch( const IO_ERROR& ioe ) { if( ioe.Problem() != wxT( "CANCEL" ) ) { wxString msg = wxString::Format( _( "Error loading board file:\n%s" ), fullFileName ); DisplayErrorMessage( this, msg, ioe.What() ); } return false; } // 6.0 TODO: some settings didn't make it into the board file in 5.1 so as not to // change the file format. For 5.1 we must copy them across from the config-initialized // board. BOARD_DESIGN_SETTINGS& bds = loadedBoard->m_designSettings; BOARD_DESIGN_SETTINGS& configBds = GetBoard()->GetDesignSettings(); bds.m_RequireCourtyards = configBds.m_RequireCourtyards; bds.m_ProhibitOverlappingCourtyards = configBds.m_ProhibitOverlappingCourtyards; bds.m_HoleToHoleMin = configBds.m_HoleToHoleMin; bds.m_LineThickness[LAYER_CLASS_OTHERS] = configBds.m_LineThickness[LAYER_CLASS_OTHERS]; bds.m_TextSize[LAYER_CLASS_OTHERS] = configBds.m_TextSize[LAYER_CLASS_OTHERS]; bds.m_TextThickness[LAYER_CLASS_OTHERS] = configBds.m_TextThickness[LAYER_CLASS_OTHERS]; std::copy( configBds.m_TextItalic, configBds.m_TextItalic + 4, bds.m_TextItalic ); std::copy( configBds.m_TextUpright, configBds.m_TextUpright + 4, bds.m_TextUpright ); bds.m_DiffPairDimensionsList = configBds.m_DiffPairDimensionsList; bds.m_CopperEdgeClearance = configBds.m_CopperEdgeClearance; SetBoard( loadedBoard ); // we should not ask PLUGINs to do these items: loadedBoard->BuildListOfNets(); loadedBoard->SynchronizeNetsAndNetClasses(); // If this is a legacy board then we set the copper edge clearance to 1/2 the edge-cut // line width (which was a legacy kludge for implementing edge clearances). if( bds.m_CopperEdgeClearance == Millimeter2iu( LEGACY_COPPEREDGECLEARANCE ) ) bds.SetCopperEdgeClearance( inferLegacyEdgeClearance( loadedBoard ) ); if( loadedBoard->IsModified() ) OnModify(); else GetScreen()->ClrModify(); if( pluginType == IO_MGR::LEGACY && loadedBoard->GetFileFormatVersionAtLoad() < LEGACY_BOARD_FILE_VERSION ) { DisplayInfoMessage( this, _( "This file was created by an older version of Pcbnew.\n" "It will be stored in the new file format when you save this file again." ) ); } } { wxFileName fn = fullFileName; if( converted ) fn.SetExt( PcbFileExtension ); wxString fname = fn.GetFullPath(); fname.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP ); GetBoard()->SetFileName( fname ); } // Lock the file newly opened: m_file_checker.reset( lockFile.release() ); if( !converted ) UpdateFileHistory( GetBoard()->GetFileName() ); // Rebuild the new pad list (for drc and ratsnet control ...) GetBoard()->m_Status_Pcb = 0; // Select netclass Default as current netclass (it always exists) SetCurrentNetClass( NETCLASS::Default ); // Rebuild list of nets (full ratsnest rebuild) Compile_Ratsnest( NULL, true ); GetBoard()->BuildConnectivity(); onBoardLoaded(); // Refresh the 3D view, if any EDA_3D_VIEWER* draw3DFrame = Get3DViewerFrame(); if( draw3DFrame ) draw3DFrame->NewDisplay(); #if 0 && defined(DEBUG) // Output the board object tree to stdout, but please run from command prompt: GetBoard()->Show( 0, std::cout ); #endif // from EDA_APPL which was first loaded BOARD only: { /* For an obscure reason the focus is lost after loading a board file * when starting up the process. * (seems due to the recreation of the layer manager after loading the file) * Give focus to main window and Drawpanel * must be done for these 2 windows (for an obscure reason ...) * Linux specific * This is more a workaround than a fix. */ SetFocus(); GetCanvas()->SetFocus(); } return true; }
bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl ) { // implement the pseudo code from KIWAY_PLAYER.h: SCH_SCREENS screenList; // This is for python: if( aFileSet.size() != 1 ) { UTF8 msg = StrPrintf( "Eeschema:%s() takes only a single filename", __func__ ); DisplayError( this, msg ); return false; } wxString fullFileName( aFileSet[0] ); // We insist on caller sending us an absolute path, if it does not, we say it's a bug. wxASSERT_MSG( wxFileName( fullFileName ).IsAbsolute(), wxT( "bug in single_top.cpp or project manager." ) ); if( !LockFile( fullFileName ) ) { wxString msg = wxString::Format( _( "Schematic file '%s' is already open." ), GetChars( fullFileName ) ); DisplayError( this, msg ); return false; } // save any currently open and modified project files. for( SCH_SCREEN* screen = screenList.GetFirst(); screen; screen = screenList.GetNext() ) { if( screen->IsModify() ) { int response = YesNoCancelDialog( this, _( "The current schematic has been modified. Do you wish to save the changes?" ), wxEmptyString, _( "Save and Load" ), _( "Load Without Saving" ) ); if( response == wxID_CANCEL ) { return false; } else if( response == wxID_YES ) { wxCommandEvent dummy; OnSaveProject( dummy ); } else { // response == wxID_NO, fall thru } break; } } wxFileName pro = fullFileName; pro.SetExt( ProjectFileExtension ); bool is_new = !wxFileName::IsFileReadable( fullFileName ); // If its a non-existent schematic and caller thinks it exists if( is_new && !( aCtl & KICTL_CREATE ) ) { // notify user that fullFileName does not exist, ask if user wants to create it. wxString ask = wxString::Format( _( "Schematic '%s' does not exist. Do you wish to create it?" ), GetChars( fullFileName ) ); if( !IsOK( this, ask ) ) return false; } // unload current project file before loading new { delete g_RootSheet; g_RootSheet = NULL; CreateScreens(); } GetScreen()->SetFileName( fullFileName ); g_RootSheet->SetFileName( fullFileName ); SetStatusText( wxEmptyString ); ClearMsgPanel(); wxString msg = wxString::Format( _( "Ready\nProject dir: '%s'\n" ), GetChars( wxPathOnly( Prj().GetProjectFullName() ) ) ); SetStatusText( msg ); // PROJECT::SetProjectFullName() is an impactful function. It should only be // called under carefully considered circumstances. // The calling code should know not to ask me here to change projects unless // it knows what consequences that will have on other KIFACEs running and using // this same PROJECT. It can be very harmful if that calling code is stupid. Prj().SetProjectFullName( pro.GetFullPath() ); LoadProjectFile(); // load the libraries here, not in SCH_SCREEN::Draw() which is a context // that will not tolerate DisplayError() dialog since we're already in an // event handler in there. // And when a schematic file is loaded, we need these libs to initialize // some parameters (links to PART LIB, dangling ends ...) Prj().SchLibs(); if( is_new ) { // mark new, unsaved file as modified. GetScreen()->SetModify(); } else { g_RootSheet->SetScreen( NULL ); DBG( printf( "%s: loading schematic %s\n", __func__, TO_UTF8( fullFileName ) );) bool diag = g_RootSheet->Load( this ); (void) diag; SetScreen( m_CurrentSheet->LastScreen() ); GetScreen()->ClrModify(); UpdateFileHistory( fullFileName ); }
void KICAD_MANAGER_FRAME::OnLoadProject( wxCommandEvent& event ) { // Any open KIFACE's must be closed if they are not part of the new project. // (We never want a KIWAY_PLAYER open on a KIWAY that isn't in the same project.) // User is prompted here to close those KIWAY_PLAYERs: if( !Kiway.PlayersClose( false ) ) return; // evt_id can be one of: // ID_NEW_PROJECT, ID_NEW_PROJECT_FROM_TEMPLATE, ID_LOAD_PROJECT, and // wxID_ANY from 3 different places. int evt_id = event.GetId(); wxString title; ClearMsg(); bool newProject = ( evt_id == ID_NEW_PROJECT ) || ( evt_id == ID_NEW_PROJECT_FROM_TEMPLATE ); if( evt_id != wxID_ANY ) { int style; if( newProject ) { title = _( "Create New Project" ); style = wxFD_SAVE | wxFD_OVERWRITE_PROMPT; } else { title = _( "Open Existing Project" ); style = wxFD_OPEN | wxFD_FILE_MUST_EXIST; } wxString default_dir = GetMruPath(); wxFileDialog dlg( this, title, default_dir, wxEmptyString, ProjectFileWildcard, style ); if( dlg.ShowModal() == wxID_CANCEL ) return; //DBG( printf( "%s: wxFileDialog::GetPath=%s\n", __func__, TO_UTF8( dlg.GetPath() ) );) wxFileName pro( dlg.GetPath() ); pro.SetExt( ProjectFileExtension ); // enforce extension if( !pro.IsAbsolute() ) pro.MakeAbsolute(); if( newProject ) { // Check if the project directory is empty wxDir directory( pro.GetPath() ); if( directory.HasFiles() ) { wxString msg = _( "The selected directory is not empty. We recommend you " "create projects in their own clean directory.\n\nDo you " "want to create a new empty directory for the project?" ); if( IsOK( this, msg ) ) { // Append a new directory with the same name of the project file // and try to create it pro.AppendDir( pro.GetName() ); if( !wxMkdir( pro.GetPath() ) ) // There was a problem, undo pro.RemoveLastDir(); } } if( evt_id == ID_NEW_PROJECT ) { CreateNewProject( pro.GetFullPath() ); } else if( evt_id == ID_NEW_PROJECT_FROM_TEMPLATE ) { // Launch the template selector dialog CreateNewProject( pro.GetFullPath(), true ); } } SetProjectFileName( pro.GetFullPath() ); } wxString prj_filename = GetProjectFileName(); wxString nameless_prj = NAMELESS_PROJECT wxT( ".pro" ); wxLogDebug( wxT( "%s: %s" ), GetChars( wxFileName( prj_filename ).GetFullName() ), GetChars( nameless_prj ) ); // Check if project file exists and if it is not noname.pro if( !wxFileExists( prj_filename ) && !wxFileName( prj_filename ).GetFullName().IsSameAs( nameless_prj ) ) { wxString msg = wxString::Format( _( "KiCad project file '%s' not found" ), GetChars( prj_filename ) ); DisplayError( this, msg ); return; } // Either this is the first time kicad has been run or one of the projects in the // history list is no longer valid. This prevents kicad from automatically creating // a noname.pro file in the same folder as the kicad binary. if( wxFileName( prj_filename ).GetFullName().IsSameAs( nameless_prj ) && !newProject ) { m_active_project = false; m_MessagesBox->SetValue( _( "To proceed, you can use the File menu to start a new project." ) ); return; } else { m_active_project = true; m_MessagesBox->Clear(); } Prj().ConfigLoad( Pgm().SysSearch(), GeneralGroupName, s_KicadManagerParams ); title = wxT( "KiCad " ) + GetBuildVersion() + wxT( ' ' ) + prj_filename; if( !wxFileName( prj_filename ).IsDirWritable() ) title += _( " [Read Only]" ); else SetMruPath( Prj().GetProjectPath() ); // Only set MRU path if we have write access. SetTitle( title ); if( !prj_filename.IsSameAs( nameless_prj ) ) UpdateFileHistory( prj_filename, &Pgm().GetFileHistory() ); m_LeftWin->ReCreateTreePrj(); // Rebuild the list of watched paths. // however this is possible only when the main loop event handler is running, // so we use it to run the rebuild function. wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED, ID_INIT_WATCHED_PATHS ); wxPostEvent( this, cmd ); PrintPrjInfo(); }
bool SCH_EDIT_FRAME::LoadOneEEProject( const wxString& aFileName, bool aIsNew ) { SCH_SCREEN* screen; wxString FullFileName, msg; bool LibCacheExist = false; SCH_SCREENS ScreenList; for( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() ) { if( screen->IsModify() ) break; } if( screen ) { int response = YesNoCancelDialog( this, _( "The current schematic has been modified. Do " "you wish to save the changes?" ), wxEmptyString, _( "Save and Load" ), _( "Load Without Saving" ) ); if( response == wxID_CANCEL ) { return false; } else if( response == wxID_YES ) { wxCommandEvent dummy; OnSaveProject( dummy ); } } FullFileName = aFileName; if( FullFileName.IsEmpty() && !aIsNew ) { wxFileDialog dlg( this, _( "Open Schematic" ), wxGetCwd(), wxEmptyString, SchematicFileWildcard, wxFD_OPEN | wxFD_FILE_MUST_EXIST ); if( dlg.ShowModal() == wxID_CANCEL ) return false; FullFileName = dlg.GetPath(); } wxFileName fn = FullFileName; if( fn.IsRelative() ) { fn.MakeAbsolute(); FullFileName = fn.GetFullPath(); } if( !wxGetApp().LockFile( FullFileName ) ) { DisplayError( this, _( "This file is already open." ) ); return false; } // Clear the screen before open a new file if( g_RootSheet ) { delete g_RootSheet; g_RootSheet = NULL; } CreateScreens(); screen = GetScreen(); wxLogDebug( wxT( "Loading schematic " ) + FullFileName ); wxSetWorkingDirectory( fn.GetPath() ); screen->SetFileName( FullFileName ); g_RootSheet->SetFileName( FullFileName ); SetStatusText( wxEmptyString ); ClearMsgPanel(); screen->ClrModify(); if( aIsNew ) { /* SCH_SCREEN constructor does this now screen->SetPageSettings( PAGE_INFO( wxT( "A4" ) ) ); */ screen->SetZoom( 32 ); screen->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId ); TITLE_BLOCK tb; wxString title; title += NAMELESS_PROJECT; title += wxT( ".sch" ); tb.SetTitle( title ); screen->SetTitleBlock( tb ); GetScreen()->SetFileName( title ); LoadProjectFile( wxEmptyString, true ); Zoom_Automatique( false ); SetSheetNumberAndCount(); m_canvas->Refresh(); return true; } // Reloading configuration. msg.Printf( _( "Ready\nWorking dir: <%s>\n" ), GetChars( wxGetCwd() ) ); PrintMsg( msg ); LoadProjectFile( wxEmptyString, false ); // Clear (if needed) the current active library in libedit because it could be // removed from memory LIB_EDIT_FRAME::EnsureActiveLibExists(); // Delete old caches. CMP_LIBRARY::RemoveCacheLibrary(); LibCacheExist = LoadCacheLibrary( g_RootSheet->GetScreen()->GetFileName() ); if( !wxFileExists( g_RootSheet->GetScreen()->GetFileName() ) && !LibCacheExist ) { Zoom_Automatique( false ); msg.Printf( _( "File <%s> not found." ), GetChars( g_RootSheet->GetScreen()->GetFileName() ) ); DisplayInfoMessage( this, msg ); return false; } // load the project. g_RootSheet->SetScreen( NULL ); bool diag = g_RootSheet->Load( this ); SetScreen( m_CurrentSheet->LastScreen() ); UpdateFileHistory( g_RootSheet->GetScreen()->GetFileName() ); /* Redraw base screen (ROOT) if necessary. */ GetScreen()->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId ); Zoom_Automatique( false ); SetSheetNumberAndCount(); m_canvas->Refresh( true ); return diag; }
bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl ) { // This is for python: if( aFileSet.size() != 1 ) { UTF8 msg = StrPrintf( "Pcbnew:%s() takes only a single filename", __func__ ); DisplayError( this, msg ); return false; } wxString fullFileName( aFileSet[0] ); // We insist on caller sending us an absolute path, if it does not, we say it's a bug. wxASSERT_MSG( wxFileName( fullFileName ).IsAbsolute(), wxT( "bug in single_top.cpp or project manager." ) ); if( !LockFile( fullFileName ) ) { wxString msg = wxString::Format( _( "PCB file '%s' is already open." ), GetChars( fullFileName ) ); DisplayError( this, msg ); return false; } if( GetScreen()->IsModify() ) { int response = YesNoCancelDialog( this, _( "The current board has been modified. Do you wish to save the changes?" ), wxEmptyString, _( "Save and Load" ), _( "Load Without Saving" ) ); if( response == wxID_CANCEL ) return false; else if( response == wxID_YES ) SavePcbFile( GetBoard()->GetFileName(), CREATE_BACKUP_FILE ); else { // response == wxID_NO, fall thru } } wxFileName pro = fullFileName; pro.SetExt( ProjectFileExtension ); bool is_new = !wxFileName::IsFileReadable( fullFileName ); // If its a non-existent schematic and caller thinks it exists if( is_new && !( aCtl & KICTL_CREATE ) ) { // notify user that fullFileName does not exist, ask if user wants to create it. wxString ask = wxString::Format( _( "Board '%s' does not exist. Do you wish to create it?" ), GetChars( fullFileName ) ); if( !IsOK( this, ask ) ) return false; } Clear_Pcb( false ); // pass false since we prompted above for a modified board IO_MGR::PCB_FILE_T pluginType = plugin_type( fullFileName, aCtl ); bool converted = pluginType != IO_MGR::LEGACY && pluginType != IO_MGR::KICAD; if( !converted ) { // PROJECT::SetProjectFullName() is an impactful function. It should only be // called under carefully considered circumstances. // The calling code should know not to ask me here to change projects unless // it knows what consequences that will have on other KIFACEs running and using // this same PROJECT. It can be very harmful if that calling code is stupid. Prj().SetProjectFullName( pro.GetFullPath() ); // load project settings before BOARD LoadProjectSettings(); } if( is_new ) { OnModify(); } else { BOARD* loadedBoard = 0; // it will be set to non-NULL if loaded OK PLUGIN::RELEASER pi( IO_MGR::PluginFind( pluginType ) ); try { PROPERTIES props; char xbuf[30]; char ybuf[30]; // EAGLE_PLUGIN can use this info to center the BOARD, but it does not yet. sprintf( xbuf, "%d", GetPageSizeIU().x ); sprintf( ybuf, "%d", GetPageSizeIU().y ); props["page_width"] = xbuf; props["page_height"] = ybuf; #if USE_INSTRUMENTATION // measure the time to load a BOARD. unsigned startTime = GetRunningMicroSecs(); #endif loadedBoard = pi->Load( fullFileName, NULL, &props ); #if USE_INSTRUMENTATION unsigned stopTime = GetRunningMicroSecs(); printf( "PLUGIN::Load(): %u usecs\n", stopTime - startTime ); #endif } catch( const IO_ERROR& ioe ) { wxString msg = wxString::Format( _( "Error loading board.\n%s" ), GetChars( ioe.errorText ) ); DisplayError( this, msg ); return false; } SetBoard( loadedBoard ); // we should not ask PLUGINs to do these items: loadedBoard->BuildListOfNets(); loadedBoard->SynchronizeNetsAndNetClasses(); SetStatusText( wxEmptyString ); BestZoom(); // update the layer names in the listbox ReCreateLayerBox( false ); GetScreen()->ClrModify(); { wxFileName fn = fullFileName; CheckForAutoSaveFile( fullFileName, fn.GetExt() ); } if( pluginType == IO_MGR::LEGACY && loadedBoard->GetFileFormatVersionAtLoad() < LEGACY_BOARD_FILE_VERSION ) { DisplayInfoMessage( this, _( "This file was created by an older version of Pcbnew.\n" "It will be stored in the new file format when you save this file again." ) ); } } { wxFileName fn = fullFileName; if( converted ) fn.SetExt( PcbFileExtension ); wxString fname = fn.GetFullPath(); fname.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP ); GetBoard()->SetFileName( fname ); } UpdateTitle(); if( !converted ) UpdateFileHistory( GetBoard()->GetFileName() ); // Rebuild the new pad list (for drc and ratsnet control ...) GetBoard()->m_Status_Pcb = 0; // Update info shown by the horizontal toolbars SetCurrentNetClass( NETCLASS::Default ); ReFillLayerWidget(); ReCreateLayerBox(); // upate the layer widget to match board visibility states, both layers and render columns. syncLayerVisibilities(); syncLayerWidgetLayer(); syncRenderStates(); // Update the tracks / vias available sizes list: ReCreateAuxiliaryToolbar(); // Update the RATSNEST items, which were not loaded at the time // BOARD::SetVisibleElements() was called from within any PLUGIN. // See case RATSNEST_VISIBLE: in BOARD::SetElementVisibility() GetBoard()->SetVisibleElements( GetBoard()->GetVisibleElements() ); // Display the loaded board: Zoom_Automatique( false ); // Compile ratsnest and displays net info { wxBusyCursor dummy; // Displays an Hourglass while building connectivity Compile_Ratsnest( NULL, true ); GetBoard()->GetRatsnest()->ProcessBoard(); } SetMsgPanel( GetBoard() ); // Refresh the 3D view, if any if( m_Draw3DFrame ) m_Draw3DFrame->NewDisplay(); #if 0 && defined(DEBUG) // Output the board object tree to stdout, but please run from command prompt: GetBoard()->Show( 0, std::cout ); #endif // from EDA_APPL which was first loaded BOARD only: { /* For an obscure reason the focus is lost after loading a board file * when starting up the process. * (seems due to the recreation of the layer manager after loading the file) * Give focus to main window and Drawpanel * must be done for these 2 windows (for an obscure reason ...) * Linux specific * This is more a workaround than a fix. */ SetFocus(); GetCanvas()->SetFocus(); } return true; }
bool GERBVIEW_FRAME::LoadExcellonFiles( const wxString& aFullFileName ) { wxString filetypes; wxArrayString filenamesList; wxFileName filename = aFullFileName; wxString currentPath; if( !filename.IsOk() ) { filetypes = DrillFileWildcard(); filetypes << wxT( "|" ); /* All filetypes */ filetypes += wxGetTranslation( AllFilesWildcard ); /* Use the current working directory if the file name path does not exist. */ if( filename.DirExists() ) currentPath = filename.GetPath(); else currentPath = m_mruPath; wxFileDialog dlg( this, _( "Open Drill File" ), currentPath, filename.GetFullName(), filetypes, wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE | wxFD_CHANGE_DIR ); if( dlg.ShowModal() == wxID_CANCEL ) return false; dlg.GetPaths( filenamesList ); currentPath = wxGetCwd(); m_mruPath = currentPath; } else { filenamesList.Add( aFullFileName ); currentPath = filename.GetPath(); m_mruPath = currentPath; } // Read Excellon drill files: each file is loaded on a new GerbView layer bool success = true; int layer = GetActiveLayer(); // Manage errors when loading files wxString msg; WX_STRING_REPORTER reporter( &msg ); for( unsigned ii = 0; ii < filenamesList.GetCount(); ii++ ) { filename = filenamesList[ii]; if( !filename.IsAbsolute() ) filename.SetPath( currentPath ); m_lastFileName = filename.GetFullPath(); SetActiveLayer( layer, false ); if( Read_EXCELLON_File( filename.GetFullPath() ) ) { // Update the list of recent drill files. UpdateFileHistory( filename.GetFullPath(), &m_drillFileHistory ); layer = getNextAvailableLayer( layer ); if( layer == NO_AVAILABLE_LAYERS && ii < filenamesList.GetCount()-1 ) { success = false; reporter.Report( MSG_NO_MORE_LAYER, REPORTER::RPT_ERROR ); // Report the name of not loaded files: ii += 1; while( ii < filenamesList.GetCount() ) { filename = filenamesList[ii++]; wxString txt; txt.Printf( MSG_NOT_LOADED, GetChars( filename.GetFullName() ) ); reporter.Report( txt, REPORTER::RPT_ERROR ); } break; } SetActiveLayer( layer, false ); } } if( !success ) { HTML_MESSAGE_BOX mbox( this, _( "Errors" ) ); mbox.ListSet( msg ); mbox.ShowModal(); } Zoom_Automatique( false ); // Synchronize layers tools with actual active layer: ReFillLayerWidget(); SetActiveLayer( GetActiveLayer() ); m_LayersManager->UpdateLayerIcons(); syncLayerBox(); return success; }
bool GERBVIEW_FRAME::LoadGerberFiles( const wxString& aFullFileName ) { wxString filetypes; wxArrayString filenamesList; wxFileName filename = aFullFileName; wxString currentPath; if( !filename.IsOk() ) { /* Standard gerber filetypes * (See http://en.wikipedia.org/wiki/Gerber_File) * the .gbr (.pho in legacy files) extension is the default used in Pcbnew * However there are a lot of other extensions used for gerber files * Because the first letter is usually g, we accept g* as extension * (Mainly internal copper layers do not have specific extension, * and filenames are like *.g1, *.g2 *.gb1 ...). * Now (2014) Ucamco (the company which manages the Gerber format) encourages * use of .gbr only and the Gerber X2 file format. */ filetypes = _( "Gerber files (.g* .lgr .pho)" ); filetypes << wxT("|"); filetypes += wxT("*.g*;*.G*;*.pho;*.PHO" ); filetypes << wxT("|"); /* Special gerber filetypes */ filetypes += _( "Top layer (*.GTL)|*.GTL;*.gtl|" ); filetypes += _( "Bottom layer (*.GBL)|*.GBL;*.gbl|" ); filetypes += _( "Bottom solder resist (*.GBS)|*.GBS;*.gbs|" ); filetypes += _( "Top solder resist (*.GTS)|*.GTS;*.gts|" ); filetypes += _( "Bottom overlay (*.GBO)|*.GBO;*.gbo|" ); filetypes += _( "Top overlay (*.GTO)|*.GTO;*.gto|" ); filetypes += _( "Bottom paste (*.GBP)|*.GBP;*.gbp|" ); filetypes += _( "Top paste (*.GTP)|*.GTP;*.gtp|" ); filetypes += _( "Keep-out layer (*.GKO)|*.GKO;*.gko|" ); filetypes += _( "Mechanical layers (*.GMx)|*.GM1;*.gm1;*.GM2;*.gm2;*.GM3;*.gm3|" ); filetypes += _( "Top Pad Master (*.GPT)|*.GPT;*.gpt|" ); filetypes += _( "Bottom Pad Master (*.GPB)|*.GPB;*.gpb|" ); // All filetypes filetypes += AllFilesWildcard; // Use the current working directory if the file name path does not exist. if( filename.DirExists() ) currentPath = filename.GetPath(); else { currentPath = m_mruPath; // On wxWidgets 3.1 (bug?) the path in wxFileDialog is ignored when // finishing by the dir separator. Remove it if any: if( currentPath.EndsWith( '\\' ) || currentPath.EndsWith( '/' ) ) currentPath.RemoveLast(); } wxFileDialog dlg( this, _( "Open Gerber File" ), currentPath, filename.GetFullName(), filetypes, wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE | wxFD_CHANGE_DIR ); if( dlg.ShowModal() == wxID_CANCEL ) return false; dlg.GetPaths( filenamesList ); // @todo Take a closer look at the CWD switching here. The current working directory // gets changed by wxFileDialog because the wxFD_CHANGE_DIR flag is set. Is this the // appropriate behavior? The current working directory is not returned to the previous // value so this may be an issue elsewhere. currentPath = wxGetCwd(); m_mruPath = currentPath; } else { filenamesList.Add( aFullFileName ); currentPath = filename.GetPath(); m_mruPath = currentPath; } // Set the busy cursor wxBusyCursor wait; // Read gerber files: each file is loaded on a new GerbView layer bool success = true; int layer = GetActiveLayer(); // Manage errors when loading files wxString msg; WX_STRING_REPORTER reporter( &msg ); for( unsigned ii = 0; ii < filenamesList.GetCount(); ii++ ) { filename = filenamesList[ii]; if( !filename.IsAbsolute() ) filename.SetPath( currentPath ); m_lastFileName = filename.GetFullPath(); SetActiveLayer( layer, false ); if( Read_GERBER_File( filename.GetFullPath() ) ) { UpdateFileHistory( m_lastFileName ); layer = getNextAvailableLayer( layer ); if( layer == NO_AVAILABLE_LAYERS && ii < filenamesList.GetCount()-1 ) { success = false; reporter.Report( MSG_NO_MORE_LAYER, REPORTER::RPT_ERROR ); // Report the name of not loaded files: ii += 1; while( ii < filenamesList.GetCount() ) { filename = filenamesList[ii++]; wxString txt; txt.Printf( MSG_NOT_LOADED, GetChars( filename.GetFullName() ) ); reporter.Report( txt, REPORTER::RPT_ERROR ); } break; } SetActiveLayer( layer, false ); } } if( !success ) { HTML_MESSAGE_BOX mbox( this, _( "Errors" ) ); mbox.ListSet( msg ); mbox.ShowModal(); } Zoom_Automatique( false ); // Synchronize layers tools with actual active layer: ReFillLayerWidget(); SetActiveLayer( GetActiveLayer() ); m_LayersManager->UpdateLayerIcons(); syncLayerBox(); return success; }
bool GERBVIEW_FRAME::LoadExcellonFiles( const wxString& aFullFileName ) { wxString filetypes; wxArrayString filenamesList; wxFileName filename = aFullFileName; wxString currentPath; if( !filename.IsOk() ) { filetypes = wxGetTranslation( DrillFileWildcard ); filetypes << wxT("|"); /* All filetypes */ filetypes += wxGetTranslation( AllFilesWildcard ); /* Use the current working directory if the file name path does not exist. */ if( filename.DirExists() ) currentPath = filename.GetPath(); else currentPath = wxGetCwd(); wxFileDialog dlg( this, _( "Open Drill File" ), currentPath, filename.GetFullName(), filetypes, wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE | wxFD_CHANGE_DIR ); if( dlg.ShowModal() == wxID_CANCEL ) return false; dlg.GetPaths( filenamesList ); currentPath = wxGetCwd(); } else { wxFileName filename = aFullFileName; filenamesList.Add( aFullFileName ); currentPath = filename.GetPath(); } // Read gerber files: each file is loaded on a new GerbView layer int layer = getActiveLayer(); for( unsigned ii = 0; ii < filenamesList.GetCount(); ii++ ) { wxFileName filename = filenamesList[ii]; if( !filename.IsAbsolute() ) filename.SetPath( currentPath ); m_lastFileName = filename.GetFullPath(); setActiveLayer( layer, false ); if( Read_EXCELLON_File( filename.GetFullPath() ) ) { // Update the list of recentdrill files. UpdateFileHistory( filename.GetFullPath(), &m_drillFileHistory ); layer = getNextAvailableLayer( layer ); if( layer == NO_AVAILABLE_LAYERS ) { wxString msg = wxT( "No more empty layers are available. The remaining gerber " ); msg += wxT( "files will not be loaded." ); wxMessageBox( msg ); break; } setActiveLayer( layer, false ); } } Zoom_Automatique( false ); // Synchronize layers tools with actual active layer: setActiveLayer( getActiveLayer() ); m_LayersManager->UpdateLayerIcons(); syncLayerBox(); return true; }
bool GERBVIEW_FRAME::LoadGerberFiles( const wxString& aFullFileName ) { wxString filetypes; wxArrayString filenamesList; wxFileName filename = aFullFileName; wxString currentPath; if( !filename.IsOk() ) { /* Standard gerber filetypes * (See http://en.wikipedia.org/wiki/Gerber_File) * the .pho extension is the default used in Pcbnew * However there are a lot of other extensions used for gerber files * Because the first letter is usually g, we accept g* as extension * (Mainly internal copper layers do not have specific extention, * and filenames are like *.g1, *.g2 *.gb1 ...). */ filetypes = _( "Gerber files (.g* .lgr .pho)" ); filetypes << wxT("|"); filetypes += wxT("*.g*;*.G*;*.lgr;*.LGR;*.pho;*.PHO" ); filetypes << wxT("|"); /* Special gerber filetypes */ filetypes += _( "Top layer (*.GTL)|*.GTL;*.gtl|" ); filetypes += _( "Bottom layer (*.GBL)|*.GBL;*.gbl|" ); filetypes += _( "Bottom solder resist (*.GBS)|*.GBS;*.gbs|" ); filetypes += _( "Top solder resist (*.GTS)|*.GTS;*.gts|" ); filetypes += _( "Bottom overlay (*.GBO)|*.GBO;*.gbo|" ); filetypes += _( "Top overlay (*.GTO)|*.GTO;*.gto|" ); filetypes += _( "Bottom paste (*.GBP)|*.GBP;*.gbp|" ); filetypes += _( "Top paste (*.GTP)|*.GTP;*.gtp|" ); filetypes += _( "Keep-out layer (*.GKO)|*.GKO;*.gko|" ); filetypes += _( "Mechanical layers (*.GMx)|*.GM1;*.gm1;*.GM2;*.gm2;*.GM3;*.gm3|" ); filetypes += _( "Top Pad Master (*.GPT)|*.GPT;*.gpt|" ); filetypes += _( "Bottom Pad Master (*.GPB)|*.GPB;*.gpb|" ); /* All filetypes */ filetypes += AllFilesWildcard; /* Use the current working directory if the file name path does not exist. */ if( filename.DirExists() ) currentPath = filename.GetPath(); else currentPath = wxGetCwd(); wxFileDialog dlg( this, _( "Open Gerber File" ), currentPath, filename.GetFullName(), filetypes, wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE | wxFD_CHANGE_DIR ); if( dlg.ShowModal() == wxID_CANCEL ) return false; dlg.GetPaths( filenamesList ); currentPath = wxGetCwd(); } else { wxFileName filename = aFullFileName; filenamesList.Add( aFullFileName ); currentPath = filename.GetPath(); } // Read gerber files: each file is loaded on a new GerbView layer int layer = getActiveLayer(); for( unsigned ii = 0; ii < filenamesList.GetCount(); ii++ ) { wxFileName filename = filenamesList[ii]; if( !filename.IsAbsolute() ) filename.SetPath( currentPath ); m_lastFileName = filename.GetFullPath(); setActiveLayer( layer, false ); if( Read_GERBER_File( filename.GetFullPath(), filename.GetFullPath() ) ) { UpdateFileHistory( m_lastFileName ); layer = getNextAvailableLayer( layer ); if( layer == NO_AVAILABLE_LAYERS ) { wxString msg = wxT( "No more empty layers are available. The remaining gerber " ); msg += wxT( "files will not be loaded." ); wxMessageBox( msg ); break; } setActiveLayer( layer, false ); } } Zoom_Automatique( false ); // Synchronize layers tools with actual active layer: setActiveLayer( getActiveLayer() ); m_LayersManager->UpdateLayerIcons(); syncLayerBox(); return true; }
void SCH_EDIT_FRAME::OnCloseWindow( wxCloseEvent& aEvent ) { LIB_EDIT_FRAME * libeditFrame = LIB_EDIT_FRAME::GetActiveLibraryEditor();; if( libeditFrame && !libeditFrame->Close() ) // Can close component editor? return; LIB_VIEW_FRAME* viewlibFrame = LIB_VIEW_FRAME::GetActiveLibraryViewer( this ); if( viewlibFrame && !viewlibFrame->Close() ) // Can close component viewer? return; SCH_SHEET_LIST SheetList; if( SheetList.IsModified() ) { wxString msg; msg.Printf( _("Save the changes in\n<%s>\nbefore closing?"), GetChars( g_RootSheet->GetScreen()->GetFileName() ) ); int ii = DisplayExitDialog( this, msg ); switch( ii ) { case wxID_CANCEL: aEvent.Veto(); return; case wxID_NO: break; case wxID_YES: wxCommandEvent tmp( ID_SAVE_PROJECT ); OnSaveProject( tmp ); break; } } // Close the find dialog and perserve it's setting if it is displayed. if( m_dlgFindReplace ) { m_findDialogPosition = m_dlgFindReplace->GetPosition(); m_findDialogSize = m_dlgFindReplace->GetSize(); m_findStringHistoryList = m_dlgFindReplace->GetFindEntries(); m_replaceStringHistoryList = m_dlgFindReplace->GetReplaceEntries(); m_dlgFindReplace->Destroy(); m_dlgFindReplace = NULL; } SCH_SCREENS screens; wxFileName fn; for( SCH_SCREEN* screen = screens.GetFirst(); screen != NULL; screen = screens.GetNext() ) { fn = screen->GetFileName(); // Auto save file name is the normal file name prepended with $. fn.SetName( wxT( "$" ) + fn.GetName() ); if( fn.FileExists() && fn.IsFileWritable() ) wxRemoveFile( fn.GetFullPath() ); } SheetList.ClearModifyStatus(); if( !g_RootSheet->GetScreen()->GetFileName().IsEmpty() && (g_RootSheet->GetScreen()->GetDrawItems() != NULL) ) UpdateFileHistory( g_RootSheet->GetScreen()->GetFileName() ); g_RootSheet->GetScreen()->Clear(); // all sub sheets are deleted, only the main sheet is usable m_CurrentSheet->Clear(); Destroy(); }
bool GERBVIEW_FRAME::unarchiveFiles( const wxString& aFullFileName, REPORTER* aReporter ) { wxString msg; // Extract the path of aFullFileName. We use it to store temporary files wxFileName fn( aFullFileName ); wxString unzipDir = fn.GetPath(); wxFFileInputStream zipFile( aFullFileName ); if( !zipFile.IsOk() ) { if( aReporter ) { msg.Printf( _( "Zip file \"%s\" cannot be opened" ), GetChars( aFullFileName ) ); aReporter->Report( msg, REPORTER::RPT_ERROR ); } return false; } // Update the list of recent zip files. UpdateFileHistory( aFullFileName, &m_zipFileHistory ); // The unzipped file in only a temporary file. Give it a filename // which cannot conflict with an usual filename. // TODO: make Read_GERBER_File() and Read_EXCELLON_File() able to // accept a stream, and avoid using a temp file. wxFileName temp_fn( "$tempfile.tmp" ); temp_fn.MakeAbsolute( unzipDir ); wxString unzipped_tempfile = temp_fn.GetFullPath(); bool success = true; wxZipInputStream zipArchive( zipFile ); wxZipEntry* entry; bool reported_no_more_layer = false; while( ( entry = zipArchive.GetNextEntry() ) ) { wxString fname = entry->GetName(); wxFileName uzfn = fname; wxString curr_ext = uzfn.GetExt().Lower(); // The archive contains Gerber and/or Excellon drill files. Use the right loader. // However it can contain a few other files (reports, pdf files...), // which will be skipped. // Gerber files ext is usually "gbr", but can be also an other value, starting by "g" // old gerber files ext from kicad is .pho // drill files do not have a well defined ext // It is .drl in kicad, but .txt in Altium for instance // Allows only .drl for drill files. if( curr_ext[0] != 'g' && curr_ext != "pho" && curr_ext != "drl" ) { if( aReporter ) { msg.Printf( _( "Info: skip file <i>\"%s\"</i> (unknown type)\n" ), GetChars( entry->GetName() ) ); aReporter->Report( msg, REPORTER::RPT_WARNING ); } continue; } int layer = GetActiveLayer(); if( layer == NO_AVAILABLE_LAYERS ) { success = false; if( aReporter ) { if( !reported_no_more_layer ) aReporter->Report( MSG_NO_MORE_LAYER, REPORTER::RPT_ERROR ); reported_no_more_layer = true; // Report the name of not loaded files: msg.Printf( MSG_NOT_LOADED, GetChars( entry->GetName() ) ); aReporter->Report( msg, REPORTER::RPT_ERROR ); } delete entry; continue; } // Create the unzipped temporary file: { wxFFileOutputStream temporary_ofile( unzipped_tempfile ); if( temporary_ofile.Ok() ) temporary_ofile.Write( zipArchive ); else { success = false; if( aReporter ) { msg.Printf( _( "<b>Unable to create temporary file \"%s\"</b>\n"), GetChars( unzipped_tempfile ) ); aReporter->Report( msg, REPORTER::RPT_ERROR ); } } } bool read_ok = true; if( curr_ext[0] == 'g' || curr_ext == "pho" ) { // Read gerber files: each file is loaded on a new GerbView layer read_ok = Read_GERBER_File( unzipped_tempfile ); } else // if( curr_ext == "drl" ) { read_ok = Read_EXCELLON_File( unzipped_tempfile ); } delete entry; // The unzipped file is only a temporary file, delete it. wxRemoveFile( unzipped_tempfile ); if( !read_ok ) { success = false; if( aReporter ) { msg.Printf( _("<b>unzipped file %s read error</b>\n"), GetChars( unzipped_tempfile ) ); aReporter->Report( msg, REPORTER::RPT_ERROR ); } } else { GERBER_FILE_IMAGE* gerber_image = GetGbrImage( layer ); if( gerber_image ) gerber_image->m_FileName = fname; layer = getNextAvailableLayer( layer ); SetActiveLayer( layer, false ); } } return success; }
bool CVPCB_MAINFRAME::ReadNetListAndLinkFiles() { COMPONENT* component; wxString msg; bool isLegacy = true; ReadSchematicNetlist(); if( m_ListCmp == NULL ) return false; LoadProjectFile( m_NetlistFileName.GetFullPath() ); LoadFootprintFiles(); BuildFOOTPRINTS_LISTBOX(); BuildLIBRARY_LISTBOX(); m_ListCmp->Clear(); m_undefinedComponentCnt = 0; if( m_netlist.AnyFootprintsLinked() ) { for( unsigned i = 0; i < m_netlist.GetCount(); i++ ) { component = m_netlist.GetComponent( i ); if( component->GetFPID().empty() ) continue; if( isLegacy ) { if( !component->GetFPID().IsLegacy() ) isLegacy = false; } } } else { isLegacy = false; // None of the components have footprints assigned. } wxString missingLibs; // Check if footprint links were generated before the footprint library table was implemented. if( isLegacy ) { if( m_footprintLibTable->MissingLegacyLibs( m_ModuleLibNames, &missingLibs ) ) { msg = wxT( "The following legacy libraries are defined in the project file " "were not found in the footprint library table:\n\n" ) + missingLibs; msg += wxT( "\nDo you want to update the footprint library table before " "attempting to update the assigned footprints?" ); if( IsOK( this, msg ) ) { wxCommandEvent cmd; OnEditFootprintLibraryTable( cmd ); } } msg = wxT( "Some or all of the assigned footprints contain legacy entries. Would you " "like CvPcb to attempt to convert them to the new footprint library table " "format?" ); if( IsOK( this, msg ) ) { msg.Clear(); WX_STRING_REPORTER reporter( &msg ); if( !m_footprintLibTable->ConvertFromLegacy( m_netlist, m_ModuleLibNames, &reporter ) ) { HTML_MESSAGE_BOX dlg( this, wxEmptyString ); dlg.MessageSet( wxT( "The following errors occurred attempt to convert the " "footprint assignments:\n\n" ) ); dlg.ListSet( msg ); dlg.MessageSet( wxT( "\nYou will need to reassign them manually if you want them " "to be updated correctly the next time you import the " "netlist in Pcbnew." ) ); dlg.ShowModal(); } m_modified = true; } else { // Clear the legacy footprint assignments. for( unsigned i = 0; i < m_netlist.GetCount(); i++ ) { FPID emptyFPID; component = m_netlist.GetComponent( i ); component->SetFPID( emptyFPID ); m_modified = true; } } } for( unsigned i = 0; i < m_netlist.GetCount(); i++ ) { component = m_netlist.GetComponent( i ); msg.Printf( CMP_FORMAT, m_ListCmp->GetCount() + 1, GetChars( component->GetReference() ), GetChars( component->GetValue() ), GetChars( FROM_UTF8( component->GetFPID().Format().c_str() ) ) ); m_ListCmp->AppendLine( msg ); if( component->GetFPID().empty() ) { m_undefinedComponentCnt += 1; continue; } } if( !m_netlist.IsEmpty() ) m_ListCmp->SetSelection( 0, true ); DisplayStatus(); UpdateTitle(); UpdateFileHistory( m_NetlistFileName.GetFullPath() ); return true; }