pcbnew.cpp 11.6 KB
Newer Older
1 2 3
/*
 * This program source code file is part of KiCad, a free EDA CAD application.
 *
4
 * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5
 * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
6
 * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you may find one here:
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * or you may search the http://www.gnu.org website for the version 2 license,
 * or you may write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 */

26 27
/**
 * @file pcbnew.cpp
28
 * @brief Pcbnew main program.
29
 */
30

31
#ifdef KICAD_SCRIPTING
32 33
 #include <python_scripting.h>
 #include <pcbnew_scripting_helpers.h>
34
#endif
35
#include <fctsys.h>
36 37
#include <pgm_base.h>
#include <kiface_i.h>
38 39 40 41 42 43 44
#include <confirm.h>
#include <macros.h>
#include <class_drawpanel.h>
#include <wxPcbStruct.h>
#include <eda_dde.h>
#include <pcbcommon.h>
#include <colors_selection.h>
45
#include <wx/stdpaths.h>
46 47

#include <wx/file.h>
48
#include <wx/snglinst.h>
49
#include <wx/dir.h>
50
#include <gestfich.h>
51

52 53
#include <pcbnew.h>
#include <hotkeys.h>
54
#include <wildcards_and_files_ext.h>
55
#include <class_board.h>
56 57 58 59
#include <3d_viewer.h>
#include <fp_lib_table.h>
#include <module_editor_frame.h>
#include <modview_frame.h>
60
#include <footprint_wizard_frame.h>
61

62

63 64 65
// Colors for layers and items
COLORS_DESIGN_SETTINGS g_ColorsSettings;

66 67 68 69 70 71 72
bool        g_Drc_On = true;
bool        g_AutoDeleteOldTrack = true;
bool        g_Raccord_45_Auto = true;
bool        g_Alternate_Track_Posture = false;
bool        g_Track_45_Only_Allowed = true;  // True to allow horiz, vert. and 45deg only tracks
bool        g_Segments_45_Only;              // True to allow horiz, vert. and 45deg only graphic segments
bool        g_TwoSegmentTrackBuild = true;
73

Dick Hollenbeck's avatar
Dick Hollenbeck committed
74 75
LAYER_ID    g_Route_Layer_TOP;
LAYER_ID    g_Route_Layer_BOTTOM;
76 77
int         g_MagneticPadOption   = capture_cursor_in_track_tool;
int         g_MagneticTrackOption = capture_cursor_in_track_tool;
78

79 80
wxPoint     g_Offset_Module;     // module offset used when moving a footprint

81 82
/* Name of the document footprint list
 * usually located in share/modules/footprints_doc
83
 * this is of the responsibility to users to create this file
84 85
 * if they want to have a list of footprints
 */
86
wxString    g_DocModulesFileName = wxT( "footprints_doc/footprints.pdf" );
87

88 89 90 91 92 93 94
/*
 * Used in track creation, a list of track segments currently being created,
 * with the newest track at the end of the list, sorted by new-ness.  e.g. use
 * TRACK->Back() to get the next older track, TRACK->Next() to get the next
 * newer track.
 */
DLIST<TRACK> g_CurrentTrackList;
95

96
namespace PCB {
97

98 99 100
static struct IFACE : public KIFACE_I
{
    // Of course all are virtual overloads, implementations of the KIFACE.
101

102 103 104 105
    IFACE( const char* aName, KIWAY::FACE_T aType ) :
        KIFACE_I( aName, aType )
    {}

106
    bool OnKifaceStart( PGM_BASE* aProgram, int aCtlBits );
107 108 109 110 111

    void OnKifaceEnd();

    wxWindow* CreateWindow( wxWindow* aParent, int aClassId, KIWAY* aKiway, int aCtlBits = 0 )
    {
112 113
        wxWindow* frame = NULL;

114 115
        switch( aClassId )
        {
116
        case FRAME_PCB:
117
            frame = dynamic_cast< wxWindow* >( new PCB_EDIT_FRAME( aKiway, aParent ) );
118

119 120 121
#if defined( KICAD_SCRIPTING )
            // give the scripting helpers access to our frame
            ScriptingSetPcbEditFrame( (PCB_EDIT_FRAME*) frame );
122 123
#endif

124 125 126 127
            if( Kiface().IsSingle() )
            {
                // only run this under single_top, not under a project manager.
                CreateServer( frame, KICAD_PCB_PORT_SERVICE_NUMBER );
128
            }
129

130 131
            break;

132
        case FRAME_PCB_MODULE_EDITOR:
133
            frame = dynamic_cast< wxWindow* >( new FOOTPRINT_EDIT_FRAME( aKiway, aParent ) );
134 135
            break;

136
        case FRAME_PCB_MODULE_VIEWER:
137
        case FRAME_PCB_MODULE_VIEWER_MODAL:
138 139
            frame = dynamic_cast< wxWindow* >( new FOOTPRINT_VIEWER_FRAME( aKiway, aParent,
                                                                           FRAME_T( aClassId ) ) );
140 141
            break;

142
        case FRAME_PCB_FOOTPRINT_WIZARD_MODAL:
143 144
            frame = dynamic_cast< wxWindow* >( new FOOTPRINT_WIZARD_FRAME( aKiway, aParent,
                                                                           FRAME_T( aClassId ) ) );
145 146
            break;

147 148 149 150
        default:
            ;
        }

151
        return frame;
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
    }

    /**
     * Function IfaceOrAddress
     * return a pointer to the requested object.  The safest way to use this
     * is to retrieve a pointer to a static instance of an interface, similar to
     * how the KIFACE interface is exported.  But if you know what you are doing
     * use it to retrieve anything you want.
     *
     * @param aDataId identifies which object you want the address of.
     *
     * @return void* - and must be cast into the know type.
     */
    void* IfaceOrAddress( int aDataId )
    {
        return NULL;
    }

} kiface( "pcbnew", KIWAY::FACE_PCB );

} // namespace

using namespace PCB;


static PGM_BASE* process;


KIFACE_I& Kiface() { return kiface; }


// KIFACE_GETTER's actual spelling is a substitution macro found in kiway.h.
// KIFACE_GETTER will not have name mangling due to declaration in kiway.h.
185
MY_API( KIFACE* ) KIFACE_GETTER( int* aKIFACEversion, int aKiwayVersion, PGM_BASE* aProgram )
186
{
187 188 189
    process = (PGM_BASE*) aProgram;
    return &kiface;
}
190

191
#if defined( BUILD_KIWAY_DLL )
192 193 194 195
PGM_BASE& Pgm()
{
    wxASSERT( process );    // KIFACE_GETTER has already been called.
    return *process;
196
}
197
#endif
198

199

200
#if defined( KICAD_SCRIPTING )
201
static bool scriptingSetup()
Dick Hollenbeck's avatar
Dick Hollenbeck committed
202
{
203 204
    wxString path_frag;

205
#if defined( __MINGW32__ )
206
    // force python environment under Windows:
207
    const wxString python_us( "python27_us" );
208 209

    // Build our python path inside kicad
210
    wxString kipython =  FindKicadFile( python_us + wxT( "/python.exe" ) );
211 212 213 214

    //we need only the path:
    wxFileName fn( kipython );
    kipython = fn.GetPath();
215 216 217 218 219

    // If our python install is existing inside kicad, use it
    if( wxDirExists( kipython ) )
    {
        wxString ppath;
220

221 222
        if( !wxGetEnv( wxT( "PYTHONPATH" ), &ppath ) || !ppath.Contains( python_us ) )
        {
223 224 225
            ppath << kipython << wxT( "/pylib;" );
            ppath << kipython << wxT( "/lib;" );
            ppath << kipython << wxT( "/dll" );
226
            wxSetEnv( wxT( "PYTHONPATH" ), ppath );
227
            // DBG( std::cout << "set PYTHONPATH to "  << TO_UTF8( ppath ) << "\n"; )
228 229 230

            // Add python executable path:
            wxGetEnv( wxT( "PATH" ), &ppath );
231

232 233
            if( !ppath.Contains( python_us ) )
            {
234
                kipython << wxT( ";" ) << ppath;
235
                wxSetEnv( wxT( "PATH" ), kipython );
236
                // DBG( std::cout << "set PATH to " << TO_UTF8( kipython ) << "\n"; )
237 238 239 240
            }
        }
    }

241 242 243 244
    // TODO: make this path definable by the user, and set more than one path
    // (and remove the fixed paths from <src>/scripting/kicadplugins.i)

    // wizard plugins are stored in kicad/bin/plugins.
245
    // so add this path to python scripting default search paths
246 247 248
    // which are ( [KICAD_PATH] is an environment variable to define)
    // [KICAD_PATH]/scripting/plugins
    // Add this default search path:
249
    path_frag = Pgm().GetExecutablePath() + wxT( "scripting/plugins" );
250
#elif defined( __WXMAC__ )
251
    // User plugin folder is ~/Library/Application Support/kicad/scripting/plugins
252
    path_frag = GetOSXKicadUserDataDir() + wxT( "/scripting/plugins" );
253 254 255

    // Add default paths to PYTHONPATH
    wxString pypath;
256

257
    // User scripting folder (~/Library/Application Support/kicad/scripting/plugins)
258
    pypath = GetOSXKicadUserDataDir() + wxT( "/scripting/plugins" );
259

260
    // Machine scripting folder (/Library/Application Support/kicad/scripting/plugins)
261
    pypath += wxT( ":" ) + GetOSXKicadMachineDataDir() + wxT( "/scripting/plugins" );
262

263
    // Bundle scripting folder (<kicad.app>/Contents/SharedSupport/scripting/plugins)
264
    pypath += wxT( ":" ) + GetOSXKicadDataDir() + wxT( "/scripting/plugins" );
265

266
    // Bundle wxPython folder (<kicad.app>/Contents/Frameworks/python/site-packages)
267 268 269
    pypath += wxT( ":" ) + Pgm().GetExecutablePath() +
              wxT( "Contents/Frameworks/python/site-packages" );

270
    // Original content of $PYTHONPATH
271 272
    if( wxGetenv("PYTHONPATH") != NULL )
    {
273
        pypath = wxString( wxGetenv("PYTHONPATH") ) + wxT( ":" ) + pypath;
274 275 276 277 278
    }

    // set $PYTHONPATH
    wxSetEnv( "PYTHONPATH", pypath );
#else
279
    // Add this default search path:
280
    path_frag = wxT( "/usr/local/kicad/bin/scripting/plugins" );
281
#endif
282 283

    if( !pcbnewInitPythonScripting( TO_UTF8( path_frag ) ) )
284
    {
285
        wxLogSysError( wxT( "pcbnewInitPythonScripting() failed." ) );
286
        return false;
287
    }
288

289
    return true;
Dick Hollenbeck's avatar
Dick Hollenbeck committed
290 291
}
#endif  // KICAD_SCRIPTING
292

293

Dick Hollenbeck's avatar
Dick Hollenbeck committed
294 295 296 297
/// The global footprint library table.  This is not dynamically allocated because
/// in a multiple project environment we must keep its address constant (since it is
/// the fallback table for multiple projects).
FP_LIB_TABLE    GFootprintTable;
298

dickelbeck's avatar
dickelbeck committed
299

300
bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits )
Dick Hollenbeck's avatar
Dick Hollenbeck committed
301 302
{
    // This is process level, not project level, initialization of the DSO.
303

Dick Hollenbeck's avatar
Dick Hollenbeck committed
304
    // Do nothing in here pertinent to a project!
305

306
    start_common( aCtlBits );
307

Dick Hollenbeck's avatar
Dick Hollenbeck committed
308 309
    // Must be called before creating the main frame in order to
    // display the real hotkeys in menus or tool tips
310
    ReadHotkeyConfig( PCB_EDIT_FRAME_NAME, g_Board_Editor_Hokeys_Descr );
dickelbeck's avatar
dickelbeck committed
311

Dick Hollenbeck's avatar
Dick Hollenbeck committed
312
    try
dickelbeck's avatar
dickelbeck committed
313
    {
Dick Hollenbeck's avatar
Dick Hollenbeck committed
314 315 316
        // The global table is not related to a specific project.  All projects
        // will use the same global table.  So the KIFACE::OnKifaceStart() contract
        // of avoiding anything project specific is not violated here.
317

Dick Hollenbeck's avatar
Dick Hollenbeck committed
318
        if( !FP_LIB_TABLE::LoadGlobalTable( GFootprintTable ) )
319
        {
Dick Hollenbeck's avatar
Dick Hollenbeck committed
320 321 322 323
            DisplayInfoMessage( NULL, wxT(
                "You have run Pcbnew for the first time using the "
                "new footprint library table method for finding "
                "footprints.  Pcbnew has either copied the default "
324
                "table or created an empty table in the kicad configuration "
Dick Hollenbeck's avatar
Dick Hollenbeck committed
325 326 327
                "folder.  You must first configure the library "
                "table to include all footprint libraries not "
                "included with KiCad.  See the \"Footprint Library "
328
                "Table\" section of the CvPcb or Pcbnew documentation for "
Dick Hollenbeck's avatar
Dick Hollenbeck committed
329
                "more information." ) );
330
        }
dickelbeck's avatar
dickelbeck committed
331
    }
Dick Hollenbeck's avatar
Dick Hollenbeck committed
332 333 334 335 336 337 338 339 340 341
    catch( const IO_ERROR& ioe )
    {
        wxString msg = wxString::Format( _(
            "An error occurred attempting to load the global footprint library "
            "table:\n\n%s" ),
            GetChars( ioe.errorText )
            );
        DisplayError( NULL, msg );
        return false;
    }
dickelbeck's avatar
dickelbeck committed
342

343
#if defined(KICAD_SCRIPTING)
Dick Hollenbeck's avatar
Dick Hollenbeck committed
344
    scriptingSetup();
345
#endif
346

347 348
    return true;
}
349

350

351
void IFACE::OnKifaceEnd()
352
{
353 354
    end_common();

355
#if KICAD_SCRIPTING_WXPYTHON
356 357 358
    // Restore the thread state and tell Python to cleanup after itself.
    // wxPython will do its own cleanup as part of that process.
    // This should only be called if python was setup correctly.
359

360
    pcbnewFinishPythonScripting();
361 362
#endif
}