Esempio n. 1
0
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();
}
Esempio n. 2
0
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;
}
Esempio n. 4
0
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();
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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 );
    }
Esempio n. 8
0
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();
}
Esempio n. 9
0
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;
}
Esempio n. 11
0
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;
}
Esempio n. 12
0
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;
}
Esempio n. 13
0
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;
}
Esempio n. 14
0
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;
}
Esempio n. 15
0
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();
}
Esempio n. 16
0
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;
}
Esempio n. 17
0
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;
}