KiCad PCB EDA Suite
pcbnew/files.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2004-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2011 Wayne Stambaugh <stambaughw@gmail.com>
6  * Copyright (C) 2016-2017 KiCad Developers, see AUTHORS.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
31 #include <fctsys.h>
32 #include <class_drawpanel.h>
33 #include <confirm.h>
34 #include <kicad_string.h>
35 #include <gestfich.h>
36 #include <pcb_edit_frame.h>
37 #include <macros.h>
39 #include <richio.h>
40 #include <filter_reader.h>
41 #include <pgm_base.h>
42 #include <msgpanel.h>
43 #include <fp_lib_table.h>
44 #include <ratsnest_data.h>
45 #include <kiway.h>
46 #include <kiway_player.h>
47 
48 #include <pcbnew.h>
49 #include <pcbnew_id.h>
50 #include <io_mgr.h>
52 
53 #include <class_board.h>
54 #include <build_version.h> // LEGACY_BOARD_FILE_VERSION
55 
56 #include <wx/stdpaths.h>
57 
58 
59 //#define USE_INSTRUMENTATION 1
60 #define USE_INSTRUMENTATION 0
61 
62 
63 static const wxChar backupSuffix[] = wxT( "-bak" );
64 static const wxChar autosavePrefix[] = wxT( "_autosave-" );
65 
66 
68 {
69  return wxString( autosavePrefix );
70 }
71 
72 
85 bool AskLoadBoardFileName( wxWindow* aParent, int* aCtl, wxString* aFileName, bool aKicadFilesOnly )
86 {
87  // This is a subset of all PLUGINs which are trusted to be able to
88  // load a BOARD. User may occasionally use the wrong plugin to load a
89  // *.brd file (since both legacy and eagle use *.brd extension),
90  // but eventually *.kicad_pcb will be more common than legacy *.brd files.
91  static const struct
92  {
93  const wxString& filter;
94  IO_MGR::PCB_FILE_T pluginType;
95  } loaders[] =
96  {
97  { PcbFileWildcard(), IO_MGR::KICAD_SEXP }, // Current Kicad board files
98  { LegacyPcbFileWildcard(), IO_MGR::LEGACY }, // Old Kicad board files
99  { EaglePcbFileWildcard(), IO_MGR::EAGLE }, // Import board files
100  { PCadPcbFileWildcard(), IO_MGR::PCAD }, // Import board files
101  };
102 
103  wxFileName fileName( *aFileName );
104  wxString fileFilters;
105 
106  if( aKicadFilesOnly )
107  {
108  for( unsigned ii = 0; ii < 2; ++ii )
109  {
110  if( !fileFilters.IsEmpty() )
111  fileFilters += wxChar( '|' );
112 
113  fileFilters += wxGetTranslation( loaders[ii].filter );
114  }
115  }
116  else
117  {
118  for( unsigned ii = 2; ii < DIM( loaders ); ++ii )
119  {
120  if( !fileFilters.IsEmpty() )
121  fileFilters += wxChar( '|' );
122 
123  fileFilters += wxGetTranslation( loaders[ii].filter );
124  }
125  }
126 
127  wxString path;
128  wxString name;
129 
130  if( fileName.FileExists() )
131  {
132  path = fileName.GetPath();
133  name = fileName.GetFullName();
134  }
135  else
136  {
137  path = wxStandardPaths::Get().GetDocumentsDir();
138  // leave name empty
139  }
140 
141  wxFileDialog dlg( aParent,
142  aKicadFilesOnly ? _( "Open Board File" ) : _( "Import Non KiCad Board File" ),
143  path, name, fileFilters,
144  wxFD_OPEN | wxFD_FILE_MUST_EXIST );
145 
146  if( dlg.ShowModal() == wxID_OK )
147  {
148  // For import option, if Eagle (*.brd files), tell OpenProjectFiles() to use Eagle plugin.
149  // It's the only special case because of the duplicate use of the *.brd file extension.
150  // Other cases are clear because of unique file extensions.
151  *aCtl = aKicadFilesOnly ? 0 : KICTL_EAGLE_BRD;
152  *aFileName = dlg.GetPath();
153  return true;
154  }
155  else
156  return false;
157 }
158 
159 
170 bool AskSaveBoardFileName( wxWindow* aParent, wxString* aFileName )
171 {
172  wxString wildcard = PcbFileWildcard();
173  wxFileName fn = *aFileName;
174 
175  fn.SetExt( KiCadPcbFileExtension );
176 
177  wxFileDialog dlg( aParent,
178  _( "Save Board File As" ),
179  fn.GetPath(),
180  fn.GetFullName(),
181  wildcard,
182  wxFD_SAVE | wxFD_OVERWRITE_PROMPT
183  );
184 
185  if( dlg.ShowModal() != wxID_OK )
186  return false;
187 
188  fn = dlg.GetPath();
189 
190  // always enforce filename extension, user may not have entered it.
191  fn.SetExt( KiCadPcbFileExtension );
192 
193  *aFileName = fn.GetFullPath();
194 
195  return true;
196 }
197 
198 
199 void PCB_EDIT_FRAME::OnFileHistory( wxCommandEvent& event )
200 {
201  wxString fn = GetFileFromHistory( event.GetId(), _( "Printed circuit board" ) );
202 
203  if( !!fn )
204  {
205  int open_ctl = 0;
206 
208 
209  if( !wxFileName::IsFileReadable( fn ) )
210  {
211  if( !AskLoadBoardFileName( this, &open_ctl, &fn, true ) )
212  return;
213  }
214 
215  OpenProjectFiles( std::vector<wxString>( 1, fn ), open_ctl );
216  }
217 }
218 
219 
220 void PCB_EDIT_FRAME::Files_io( wxCommandEvent& event )
221 {
222  int id = event.GetId();
223  Files_io_from_id( id );
224 }
225 
227 {
228  wxString msg;
229 
230  // If an edition is in progress, stop it.
231  // For something else than save, get rid of current tool.
232  if( id == ID_SAVE_BOARD )
234  else
236 
237  switch( id )
238  {
239  case ID_LOAD_FILE:
240  {
241  int open_ctl = 0;
242  wxString fileName = Prj().AbsolutePath( GetBoard()->GetFileName() );
243 
244  if( !AskLoadBoardFileName( this, &open_ctl, &fileName, true ) )
245  return;
246 
247  OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
248  }
249  break;
250 
252  {
253  int open_ctl = 1;
254  wxString fileName;// = Prj().AbsolutePath( GetBoard()->GetFileName() );
255 
256  if( !AskLoadBoardFileName( this, &open_ctl, &fileName, false ) )
257  return;
258 
259  OpenProjectFiles( std::vector<wxString>( 1, fileName ), open_ctl );
260  }
261  break;
262 
265  {
266  wxFileName currfn = Prj().AbsolutePath( GetBoard()->GetFileName() );
267  wxFileName fn = currfn;
268 
270  {
271  wxString rec_name = wxString( autosavePrefix ) + fn.GetName();
272  fn.SetName( rec_name );
273  }
274  else
275  {
276  wxString backup_ext = fn.GetExt()+ backupSuffix;
277  fn.SetExt( backup_ext );
278  }
279 
280  if( !fn.FileExists() )
281  {
282  msg.Printf( _( "Recovery file \"%s\" not found." ),
283  GetChars( fn.GetFullPath() ) );
284  DisplayInfoMessage( this, msg );
285  break;
286  }
287 
288  msg.Printf( _( "OK to load recovery or backup file \"%s\"" ),
289  GetChars(fn.GetFullPath() ) );
290 
291  if( !IsOK( this, msg ) )
292  break;
293 
294  GetScreen()->ClrModify(); // do not prompt the user for changes
295 
296  // LoadOnePcbFile( fn.GetFullPath(), aAppend=false, aForceFileDialog=false );
297  OpenProjectFiles( std::vector<wxString>( 1, fn.GetFullPath() ) );
298 
299  // Re-set the name since name or extension was changed
300  GetBoard()->SetFileName( currfn.GetFullPath() );
301  UpdateTitle();
302  }
303  break;
304 
305  case ID_APPEND_FILE:
306  {
307  int open_ctl;
308  wxString fileName;
309 
310  if( !AskLoadBoardFileName( this, &open_ctl, &fileName, true ) )
311  break;
312 
313  AppendBoardFile( fileName, open_ctl );
314 
315  m_canvas->Refresh();
316  }
317  break;
318 
319  case ID_NEW_BOARD:
320  {
321  if( !Clear_Pcb( true ) )
322  break;
323 
324  wxFileName fn( wxStandardPaths::Get().GetDocumentsDir(), wxT( "noname" ),
326 
327  Prj().SetProjectFullName( fn.GetFullPath() );
328 
329  fn.SetExt( PcbFileExtension );
330 
331  GetBoard()->SetFileName( fn.GetFullPath() );
332  UpdateTitle();
334  OnModify();
335  break;
336  }
337 
338  case ID_SAVE_BOARD:
339  if( ! GetBoard()->GetFileName().IsEmpty() )
340  {
341  SavePcbFile( Prj().AbsolutePath( GetBoard()->GetFileName() ) );
342  break;
343  }
344  // Fall through
345  case ID_COPY_BOARD_AS:
346  case ID_SAVE_BOARD_AS:
347  {
348  wxString pro_dir = wxPathOnly( Prj().GetProjectFullName() );
349  wxFileName fn( pro_dir, _( "noname" ), KiCadPcbFileExtension );
350  wxString filename = fn.GetFullPath();
351 
352  if( AskSaveBoardFileName( this, &filename ) )
353  {
354  if( id == ID_COPY_BOARD_AS )
355  SavePcbCopy( filename );
356  else
357  SavePcbFile( filename, NO_BACKUP_FILE );
358  }
359  }
360  break;
361 
362  default:
363  DisplayError( this, wxT( "File_io Internal Error" ) );
364  break;
365  }
366 }
367 
368 
369 // The KIWAY_PLAYER::OpenProjectFiles() API knows nothing about plugins, so
370 // determine how to load the BOARD here, with minor assistance from KICTL_EAGLE_BRD
371 // bit flag.
372 IO_MGR::PCB_FILE_T plugin_type( const wxString& aFileName, int aCtl )
373 {
374  IO_MGR::PCB_FILE_T pluginType;
375 
376  wxFileName fn = aFileName;
377 
378  // Note: file extensions are expected to be in ower case.
379  // This is not always true, especially when importing files, so the string
380  // comparisons are case insensitive to try to find the suitable plugin.
381 
382  if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::LEGACY ) ) == 0 )
383  {
384  // both legacy and eagle share a common file extension.
385  pluginType = ( aCtl & KICTL_EAGLE_BRD ) ? IO_MGR::EAGLE : IO_MGR::LEGACY;
386  }
387  else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::LEGACY ) + backupSuffix ) == 0 )
388  {
389  pluginType = IO_MGR::LEGACY;
390  }
391  else if( fn.GetExt().CmpNoCase( IO_MGR::GetFileExtension( IO_MGR::PCAD ) ) == 0 )
392  {
393  pluginType = IO_MGR::PCAD;
394  }
395  else
396  {
397  pluginType = IO_MGR::KICAD_SEXP;
398  }
399 
400  return pluginType;
401 }
402 
403 
404 bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl )
405 {
406  // This is for python:
407  if( aFileSet.size() != 1 )
408  {
409  UTF8 msg = StrPrintf( "Pcbnew:%s() takes only a single filename", __func__ );
410  DisplayError( this, msg );
411  return false;
412  }
413 
414  wxString fullFileName( aFileSet[0] );
415 
416  // We insist on caller sending us an absolute path, if it does not, we say it's a bug.
417  wxASSERT_MSG( wxFileName( fullFileName ).IsAbsolute(),
418  wxT( "bug in single_top.cpp or project manager." ) );
419 
420  if( !LockFile( fullFileName ) )
421  {
422  wxString msg = wxString::Format( _(
423  "PCB file \"%s\" is already open." ),
424  GetChars( fullFileName )
425  );
426  DisplayError( this, msg );
427  return false;
428  }
429 
430  if( GetScreen()->IsModify() )
431  {
432  int response = YesNoCancelDialog( this, _(
433  "The current board has been modified. Do you wish to save the changes?" ),
434  wxEmptyString,
435  _( "Save and Load" ),
436  _( "Load Without Saving" )
437  );
438 
439  if( response == wxID_CANCEL )
440  return false;
441  else if( response == wxID_YES )
442  SavePcbFile( GetBoard()->GetFileName(), CREATE_BACKUP_FILE );
443  else
444  {
445  // response == wxID_NO, fall thru
446  }
447  }
448 
449  wxFileName pro = fullFileName;
450  pro.SetExt( ProjectFileExtension );
451 
452  bool is_new = !wxFileName::IsFileReadable( fullFileName );
453 
454  // If its a non-existent schematic and caller thinks it exists
455  if( is_new && !( aCtl & KICTL_CREATE ) )
456  {
457  // notify user that fullFileName does not exist, ask if user wants to create it.
458  wxString ask = wxString::Format( _(
459  "Board \"%s\" does not exist. Do you wish to create it?" ),
460  GetChars( fullFileName )
461  );
462  if( !IsOK( this, ask ) )
463  return false;
464  }
465 
466  Clear_Pcb( false ); // pass false since we prompted above for a modified board
467 
468  IO_MGR::PCB_FILE_T pluginType = plugin_type( fullFileName, aCtl );
469 
470  bool converted = pluginType != IO_MGR::LEGACY && pluginType != IO_MGR::KICAD_SEXP;
471 
472  if( !converted )
473  {
474  // PROJECT::SetProjectFullName() is an impactful function. It should only be
475  // called under carefully considered circumstances.
476 
477  // The calling code should know not to ask me here to change projects unless
478  // it knows what consequences that will have on other KIFACEs running and using
479  // this same PROJECT. It can be very harmful if that calling code is stupid.
480  Prj().SetProjectFullName( pro.GetFullPath() );
481 
482  // load project settings before BOARD
484  }
485 
486  if( is_new )
487  {
488  OnModify();
489  }
490  else
491  {
492  BOARD* loadedBoard = 0; // it will be set to non-NULL if loaded OK
493 
494  PLUGIN::RELEASER pi( IO_MGR::PluginFind( pluginType ) );
495 
496  try
497  {
498  PROPERTIES props;
499  char xbuf[30];
500  char ybuf[30];
501 
502  // EAGLE_PLUGIN can use this info to center the BOARD, but it does not yet.
503  sprintf( xbuf, "%d", GetPageSizeIU().x );
504  sprintf( ybuf, "%d", GetPageSizeIU().y );
505 
506  props["page_width"] = xbuf;
507  props["page_height"] = ybuf;
508 
509 #if USE_INSTRUMENTATION
510  // measure the time to load a BOARD.
511  unsigned startTime = GetRunningMicroSecs();
512 #endif
513 
514  loadedBoard = pi->Load( fullFileName, NULL, &props );
515 
516 #if USE_INSTRUMENTATION
517  unsigned stopTime = GetRunningMicroSecs();
518  printf( "PLUGIN::Load(): %u usecs\n", stopTime - startTime );
519 #endif
520  }
521  catch( const IO_ERROR& ioe )
522  {
523  DisplayErrorMessage( this,
524  wxString::Format( _( "Error loading board file:\n%s" ), fullFileName ),
525  ioe.What() );
526  return false;
527  }
528 
529  SetBoard( loadedBoard );
530 
531  // we should not ask PLUGINs to do these items:
532  loadedBoard->BuildListOfNets();
533  loadedBoard->SynchronizeNetsAndNetClasses();
534 
535  SetStatusText( wxEmptyString );
536  Zoom_Automatique( false );
537 
538  // update the layer names in the listbox
539  ReCreateLayerBox( false );
540 
541  GetScreen()->ClrModify();
542 
543  {
544  wxFileName fn = fullFileName;
545  CheckForAutoSaveFile( fullFileName, fn.GetExt() );
546  }
547 
548  if( pluginType == IO_MGR::LEGACY &&
549  loadedBoard->GetFileFormatVersionAtLoad() < LEGACY_BOARD_FILE_VERSION )
550  {
551  DisplayInfoMessage( this,
552  _( "This file was created by an older version of Pcbnew.\n"
553  "It will be stored in the new file format when you save this file again." ) );
554  }
555  }
556 
557  {
558  wxFileName fn = fullFileName;
559 
560  if( converted )
561  fn.SetExt( PcbFileExtension );
562 
563  wxString fname = fn.GetFullPath();
564 
565  fname.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP );
566 
567  GetBoard()->SetFileName( fname );
568  }
569 
570  UpdateTitle();
571 
572  if( !converted )
573  UpdateFileHistory( GetBoard()->GetFileName() );
574 
575  // Rebuild the new pad list (for drc and ratsnet control ...)
576  GetBoard()->m_Status_Pcb = 0;
577 
578  // Select netclass Default as current netclass (it always exists)
580 
581  // Rebuild list of nets (full ratsnest rebuild)
582  Compile_Ratsnest( NULL, true );
584 
585  // Update info shown by the horizontal toolbars
588 
589  // upate the layer widget to match board visibility states, both layers and render columns.
593 
594  // Update the tracks / vias available sizes list:
596 
597  // Update the RATSNEST items, which were not loaded at the time
598  // BOARD::SetVisibleElements() was called from within any PLUGIN.
599  // See case LAYER_RATSNEST: in BOARD::SetElementVisibility()
600  GetBoard()->SetVisibleElements( GetBoard()->GetVisibleElements() );
601 
602  // Display the loaded board:
603  Zoom_Automatique( false );
604 
605  SetMsgPanel( GetBoard() );
606 
607  // Refresh the 3D view, if any
608  EDA_3D_VIEWER* draw3DFrame = Get3DViewerFrame();
609 
610  if( draw3DFrame )
611  draw3DFrame->NewDisplay();
612 
613 #if 0 && defined(DEBUG)
614  // Output the board object tree to stdout, but please run from command prompt:
615  GetBoard()->Show( 0, std::cout );
616 #endif
617 
618  // from EDA_APPL which was first loaded BOARD only:
619  {
620  /* For an obscure reason the focus is lost after loading a board file
621  * when starting up the process.
622  * (seems due to the recreation of the layer manager after loading the file)
623  * Give focus to main window and Drawpanel
624  * must be done for these 2 windows (for an obscure reason ...)
625  * Linux specific
626  * This is more a workaround than a fix.
627  */
628  SetFocus();
629  GetCanvas()->SetFocus();
630  }
631 
632  return true;
633 }
634 
635 
636 static wxString create_backup_file( const wxString& aFileName )
637 {
638  wxFileName fn = aFileName;
639  wxFileName backupFileName = aFileName;
640 
641  backupFileName.SetExt( fn.GetExt() + backupSuffix );
642 
643  // If an old backup file exists, delete it. If an old board file exists,
644  // rename it to the backup file name.
645  if( fn.FileExists() )
646  {
647  // Remove the old file xxx.000 if it exists.
648  if( backupFileName.FileExists() )
649  wxRemoveFile( backupFileName.GetFullPath() );
650 
651  // Rename the current file from <xxx>.kicad_pcb to <xxx>.kicad_pcb-bak
652  if( !wxRenameFile( fn.GetFullPath(), backupFileName.GetFullPath() ) )
653  {
654  wxString msg = wxString::Format( _(
655  "Warning: unable to create backup file \"%s\"" ),
656  GetChars( backupFileName.GetFullPath() )
657  );
658  DisplayError( NULL, msg );
659  }
660  }
661  else
662  {
663  backupFileName.Clear();
664  }
665 
666  return backupFileName.GetFullPath();
667 }
668 
669 
670 bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool aCreateBackupFile )
671 {
672  // please, keep it simple. prompting goes elsewhere.
673 
674  wxFileName pcbFileName = aFileName;
675 
676  if( pcbFileName.GetExt() == LegacyPcbFileExtension )
677  pcbFileName.SetExt( KiCadPcbFileExtension );
678 
679  if( !IsWritable( pcbFileName ) )
680  {
681  wxString msg = wxString::Format( _(
682  "No access rights to write to file \"%s\"" ),
683  GetChars( pcbFileName.GetFullPath() )
684  );
685 
686  DisplayError( this, msg );
687  return false;
688  }
689 
690  wxString backupFileName;
691 
692  // aCreateBackupFile == false is mainly used to write autosave files
693  // or new files in save as... command
694  if( aCreateBackupFile )
695  {
696  backupFileName = create_backup_file( aFileName );
697  }
698 
700 
701  // Select default Netclass before writing file.
702  // Useful to save default values in headers
704 
705  ClearMsgPanel();
706 
707  wxString upperTxt;
708  wxString lowerTxt;
709 
710  try
711  {
713 
714  wxASSERT( pcbFileName.IsAbsolute() );
715 
716  pi->Save( pcbFileName.GetFullPath(), GetBoard(), NULL );
717  }
718  catch( const IO_ERROR& ioe )
719  {
720  wxString msg = wxString::Format( _(
721  "Error saving board file \"%s\".\n%s" ),
722  GetChars( pcbFileName.GetFullPath() ),
723  GetChars( ioe.What() )
724  );
725  DisplayError( this, msg );
726 
727  lowerTxt.Printf( _( "Failed to create \"%s\"" ), GetChars( pcbFileName.GetFullPath() ) );
728 
729  AppendMsgPanel( upperTxt, lowerTxt, CYAN );
730 
731  return false;
732  }
733 
734  GetBoard()->SetFileName( pcbFileName.GetFullPath() );
735  UpdateTitle();
736 
737  // Put the saved file in File History, unless aCreateBackupFile
738  // is false.
739  // aCreateBackupFile == false is mainly used to write autosave files
740  // and not need to have an autosave file in file history
741  if( aCreateBackupFile )
742  UpdateFileHistory( GetBoard()->GetFileName() );
743 
744  // Delete auto save file on successful save.
745  wxFileName autoSaveFileName = pcbFileName;
746 
747  autoSaveFileName.SetName( wxString( autosavePrefix ) + pcbFileName.GetName() );
748 
749  if( autoSaveFileName.FileExists() )
750  wxRemoveFile( autoSaveFileName.GetFullPath() );
751 
752  if( !!backupFileName )
753  upperTxt.Printf( _( "Backup file: \"%s\"" ), GetChars( backupFileName ) );
754 
755  lowerTxt.Printf( _( "Wrote board file: \"%s\"" ), GetChars( pcbFileName.GetFullPath() ) );
756 
757  AppendMsgPanel( upperTxt, lowerTxt, CYAN );
758 
759  GetScreen()->ClrModify();
760  GetScreen()->ClrSave();
761  return true;
762 }
763 
764 
765 bool PCB_EDIT_FRAME::SavePcbCopy( const wxString& aFileName )
766 {
767  wxFileName pcbFileName = aFileName;
768 
769  // Ensure the file ext is the right ext:
770  pcbFileName.SetExt( KiCadPcbFileExtension );
771 
772  if( !IsWritable( pcbFileName ) )
773  {
774  wxString msg = wxString::Format( _(
775  "No access rights to write to file \"%s\"" ),
776  GetChars( pcbFileName.GetFullPath() )
777  );
778 
779  DisplayError( this, msg );
780  return false;
781  }
782 
784 
785  // Select default Netclass before writing file.
786  // Useful to save default values in headers
788 
789  try
790  {
792 
793  wxASSERT( pcbFileName.IsAbsolute() );
794 
795  pi->Save( pcbFileName.GetFullPath(), GetBoard(), NULL );
796  }
797  catch( const IO_ERROR& ioe )
798  {
799  wxString msg = wxString::Format( _(
800  "Error saving board file \"%s\".\n%s" ),
801  GetChars( pcbFileName.GetFullPath() ),
802  GetChars( ioe.What() )
803  );
804  DisplayError( this, msg );
805 
806  return false;
807  }
808 
809  DisplayInfoMessage( this, wxString::Format( _( "Board copied to:\n\"%s\"" ),
810  GetChars( pcbFileName.GetFullPath() ) ) );
811 
812  return true;
813 }
814 
815 
817 {
818  wxFileName tmpFileName;
819 
820  if( GetBoard()->GetFileName().IsEmpty() )
821  {
822  tmpFileName = wxFileName( wxStandardPaths::Get().GetDocumentsDir(), wxT( "noname" ),
824  GetBoard()->SetFileName( tmpFileName.GetFullPath() );
825  }
826  else
827  {
828  tmpFileName = Prj().AbsolutePath( GetBoard()->GetFileName() );
829  }
830 
831  wxFileName autoSaveFileName = tmpFileName;
832 
833  // Auto save file name is the board file name prepended with autosaveFilePrefix string.
834  autoSaveFileName.SetName( wxString( autosavePrefix ) + autoSaveFileName.GetName() );
835 
836  if( !autoSaveFileName.IsOk() )
837  return false;
838 
839  // If the board file path is not writable, try writing to a platform specific temp file
840  // path. If that path isn't writabe, give up.
841  if( !autoSaveFileName.IsDirWritable() )
842  {
843  autoSaveFileName.SetPath( wxFileName::GetTempDir() );
844 
845  if( !autoSaveFileName.IsOk() || !autoSaveFileName.IsDirWritable() )
846  return false;
847  }
848 
849  wxLogTrace( traceAutoSave, "Creating auto save file <" + autoSaveFileName.GetFullPath() + ">" );
850 
851  if( SavePcbFile( autoSaveFileName.GetFullPath(), NO_BACKUP_FILE ) )
852  {
853  GetScreen()->SetModify();
854  GetBoard()->SetFileName( tmpFileName.GetFullPath() );
855  UpdateTitle();
856  m_autoSaveState = false;
857  return true;
858  }
859 
860  GetBoard()->SetFileName( tmpFileName.GetFullPath() );
861 
862  return false;
863 }
864 
865 
866 bool PCB_EDIT_FRAME::ImportFile( const wxString& aFileName, int aFileType )
867 {
868  switch( (IO_MGR::PCB_FILE_T) aFileType )
869  {
870  case IO_MGR::EAGLE:
871  if( OpenProjectFiles( std::vector<wxString>( 1, aFileName ),
872  KICTL_EAGLE_BRD ) )
873  {
874  wxString projectpath = Kiway().Prj().GetProjectPath();
875  wxFileName newfilename = Prj().AbsolutePath( Prj().GetProjectName() );
876 
877  newfilename.SetExt( KiCadPcbFileExtension );
878 
879  GetBoard()->SetFileName( newfilename.GetFullPath() );
880  UpdateTitle();
881 
882  wxString newLibPath;
883  ArchiveModulesOnBoard( true, newfilename.GetName(), &newLibPath );
884 
885  if( newLibPath.Length()>0 )
886  {
887  FP_LIB_TABLE* prjlibtable = Prj().PcbFootprintLibs();
888  const wxString& project_env = PROJECT_VAR_NAME;
889  wxString rel_path;
890  wxString env_path;
891 
892  wxGetEnv( project_env, &env_path );
893 
894  wxString result( newLibPath );
895  rel_path = result.Replace( env_path, wxString( "$(" + project_env + ")" ) ) ? result : "" ;
896 
897  if( !rel_path.IsEmpty() ) newLibPath = rel_path;
898 
899  FP_LIB_TABLE_ROW* row = new FP_LIB_TABLE_ROW( newfilename.GetName(),
900  newLibPath,
901  wxT( "KiCad" ),
902  wxEmptyString ); // options
903  prjlibtable->InsertRow( row );
904  }
905 
906  if( !GetBoard()->GetFileName().IsEmpty() )
907  {
908  wxString tblName = Prj().FootprintLibTblName();
909 
910  try
911  {
912  Prj().PcbFootprintLibs()->Save( tblName );
913  }
914  catch( const IO_ERROR& ioe )
915  {
916  wxString msg = wxString::Format( _(
917  "Error occurred saving project specific footprint library "
918  "table:\n\n%s" ),
919  GetChars( ioe.What() )
920  );
921  wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR );
922  }
923  }
924 
925 
926  return true;
927  }
928 
929  return false;
930 
931  default:
932  return false;
933  }
934 
935  return false;
936 }
void syncRenderStates()
Function syncRenderStates updates the "Render" checkboxes in the layer widget according to current to...
void CheckForAutoSaveFile(const wxFileName &aFileName, const wxString &aBackupFileExtension)
Function CheckForAutoSaveFile checks if an auto save file exists for aFileName and takes the appropri...
void UpdateTitle()
Function UpdateTitle sets the main window title bar text.
Class UTF8 is an 8 bit string that is assuredly encoded in UTF8, and supplies special conversion supp...
Definition: utf8.h:73
#define DIM(x)
of elements in an array
Definition: macros.h:98
bool m_autoSaveState
Flag to indicate the last auto save state.
void BuildListOfNets()
Definition: class_board.h:722
virtual void OnModify() override
Function OnModify must be called after a board change to set the modified flag.
#define WIN_STRING_DIR_SEP
Definition: gestfich.h:44
KIWAY & Kiway() const
Function Kiway returns a reference to the KIWAY that this object has an opportunity to participate in...
Definition: kiway_player.h:60
wxString EaglePcbFileWildcard()
void syncLayerWidgetLayer()
Function syncLayerWidgetLayer updates the currently layer "selection" within the PCB_LAYER_WIDGET.
virtual void Save(const wxString &aFileName, BOARD *aBoard, const PROPERTIES *aProperties=NULL)
Function Save will write aBoard to a storage file in a format that this PLUGIN implementation knows a...
Definition: plugin.cpp:54
static wxString GetAutoSaveFilePrefix()
Function GetAutoSaveFilePrefix.
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Function DisplayErrorMessage displays an error message with aMessage.
Definition: confirm.cpp:255
This file is part of the common library TODO brief description.
IO_MGR::PCB_FILE_T plugin_type(const wxString &aFileName, int aCtl)
virtual void Refresh(bool eraseBackground=true, const wxRect *rect=NULL) override
Update the board display after modifying it bu a python script (note: it is automatically called by a...
Definition: draw_panel.cpp:339
Class FP_LIB_TABLE_ROW.
Definition: fp_lib_table.h:42
void SetVisibleElements(int aMask)
Function SetVisibleElements is a proxy function that calls the correspondent function in m_BoardSetti...
bool InsertRow(LIB_TABLE_ROW *aRow, bool doReplace=false)
Adds aRow if it does not already exist or if doReplace is true.
This file is part of the common library.
EDA_DRAW_PANEL * GetCanvas()
Definition: draw_frame.h:342
bool SavePcbCopy(const wxString &aFileName)
Function SavePcbCopy writes the board data structures to a aFileName but unlike SavePcbFile, does not make anything else (no backup, borad fliename change, no flag changes ...) Used under a project mgr to save under a new name the current board.
static wxString create_backup_file(const wxString &aFileName)
const wxString ProjectFileExtension
#define UNIX_STRING_DIR_SEP
Definition: gestfich.h:43
virtual bool doAutoSave() override
Function doAutoSave performs auto save when the board has been modified and not saved within the auto...
#define KICTL_CREATE
caller thinks requested project files may not exist
Definition: kiway_player.h:131
Class BOARD to handle a board.
const wxString LegacyPcbFileExtension
Class that computes missing connections on a PCB.
#define PROJECT_VAR_NAME
A variable name whose value holds the current project directory.
Definition: project.h:36
bool Clear_Pcb(bool aQuery)
Function Clear_Pcb delete all and reinitialize the current board.
Definition: initpcb.cpp:39
void EndMouseCapture(int aId=-1, int aCursorId=-1, const wxString &aTitle=wxEmptyString, bool aCallEndFunc=true)
Function EndMouseCapture ends mouse a capture.
bool LoadProjectSettings()
Load the current project&#39;s file configuration settings which are pertinent to this PCB_EDIT_FRAME ins...
void ReCreateLayerBox(bool aForceResizeToolbar=true)
Re create the layer Box by clearing the old list, and building le new one, from the new layers names ...
BOARD * GetBoard() const
#define KICTL_EAGLE_BRD
chosen *.brd file is Eagle according to user.
Definition: kiway_player.h:130
void syncLayerVisibilities()
Function syncLayerVisibilities updates each "Layer" checkbox in the layer widget according to each la...
bool IsWritable(const wxFileName &aFileName)
Function IsWritable checks if aFileName can be written.
#define NO_BACKUP_FILE
bool SetCurrentNetClass(const wxString &aNetClassName)
Function SetCurrentNetClass Must be called after a netclass selection (or after a netclass parameter ...
Class PROPERTIES is a name/value tuple with unique names and optional values.
Definition: properties.h:34
void UpdateFileHistory(const wxString &FullFileName, wxFileHistory *aFileHistory=NULL)
Function UpdateFileHistory Updates the list of recently opened files.
static const struct @13 fileFilters[FILTER_COUNT]
This file contains miscellaneous commonly used macros and functions.
int StrPrintf(std::string *result, const char *format,...)
Function StrPrintf is like sprintf() but the output is appended to a std::string instead of to a char...
Definition: richio.cpp:74
Class RELEASER releases a PLUGIN in the context of a potential thrown exception, through its destruct...
Definition: io_mgr.h:556
bool AppendBoardFile(const wxString &aFullFileName, int aCtl)
Function AppendBoardFile appends a board file onto the current one, creating God knows what...
void SynchronizeNetsAndNetClasses()
Function SynchronizeNetsAndNetClasses copies NETCLASS info to each NET, based on NET membership in a ...
Definition: netclass.cpp:158
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
void Zoom_Automatique(bool aWarpPointer)
Function Zoom_Automatique redraws the screen with best zoom level and the best centering that shows a...
Definition: zoom.cpp:102
wxString LegacyPcbFileWildcard()
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Function SetMsgPanel clears the message panel and populates it with the contents of aList...
Definition: draw_frame.cpp:790
bool OpenProjectFiles(const std::vector< wxString > &aFileSet, int aCtl=0) override
Function OpenProjectFiles (was LoadOnePcbFile) loads a KiCad board (.kicad_pcb) from aFileName...
static const char Default[]
the name of the default NETCLASS
Definition: netclass.h:90
VTBL_ENTRY PROJECT & Prj() const
Function Prj returns the PROJECT associated with this KIWAY.
Definition: kiway.cpp:142
bool AskLoadBoardFileName(wxWindow *aParent, int *aCtl, wxString *aFileName, bool aKicadFilesOnly)
Function AskLoadBoardFileName puts up a wxFileDialog asking for a BOARD filename to open...
Definition: colors.h:59
VTBL_ENTRY const wxString AbsolutePath(const wxString &aFileName) const
Function AbsolutePath fixes up aFileName if it is relative to the project&#39;s directory to be an absolu...
Definition: project.cpp:380
The common library.
void Save(const wxString &aFileName) const
Write this library table to aFileName in s-expression form.
static const wxChar backupSuffix[]
#define PcbFileExtension
void BuildConnectivity()
Builds or rebuilds the board connectivity database for the board, especially the list of connected it...
void SetFileName(const wxString &aFileName)
Definition: class_board.h:232
VTBL_ENTRY const wxString FootprintLibTblName() const
Function FootprintLibTblName returns the path and filename of this project&#39;s fp-lib-table, i.e.
Definition: project.cpp:118
VTBL_ENTRY void SetProjectFullName(const wxString &aFullPathAndName)
Function SetProjectFullName sets the: 1) full directory, 2) basename, and 3) extension of the project...
Definition: project.cpp:63
int GetFileFormatVersionAtLoad() const
Definition: class_board.h:277
void Compile_Ratsnest(wxDC *aDC, bool aDisplayStatus)
Function Compile_Ratsnest Create the entire board ratsnest.
Definition: ratsnest.cpp:54
VTBL_ENTRY FP_LIB_TABLE * PcbFootprintLibs(KIWAY &aKiway)
Return the table of footprint libraries.
static const wxChar autosavePrefix[]
EDA_DRAW_PANEL * m_canvas
The area to draw on.
Definition: draw_frame.h:93
void AppendMsgPanel(const wxString &textUpper, const wxString &textLower, COLOR4D color, int pad=6)
Append a message to the message panel.
Definition: draw_frame.cpp:770
#define CREATE_BACKUP_FILE
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:33
void OnFileHistory(wxCommandEvent &event)
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
Legacy Pcbnew file formats prior to s-expression.
Definition: io_mgr.h:54
see class PGM_BASE
void SetBoard(BOARD *aBoard) override
>
Declaration of the eda_3d_viewer class.
const char * name
Definition: DXF_plotter.cpp:61
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
void ArchiveModulesOnBoard(bool aStoreInNewLib, const wxString &aLibName=wxEmptyString, wxString *aLibPath=NULL)
Function ArchiveModulesOnBoard Save modules in a library:
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:169
void Files_io(wxCommandEvent &event)
Function Files_io.
unsigned GetRunningMicroSecs()
Function GetRunningMicroSecs An alternate way to calculate an elapset time (in microsecondes) to clas...
static PLUGIN * PluginFind(PCB_FILE_T aFileType)
Function PluginFind returns a PLUGIN which the caller can use to import, export, save, or load design documents.
Definition: io_mgr.cpp:58
bool AskSaveBoardFileName(wxWindow *aParent, wxString *aFileName)
Function AskSaveBoardFileName puts up a wxFileDialog asking for a BOARD filename to save...
wxString GetFileFromHistory(int cmdId, const wxString &type, wxFileHistory *aFileHistory=NULL)
Function GetFileFromHistory fetches the file name from the file history list.
bool ImportFile(const wxString &aFileName, int aFileType) override
Function ImportFile load the given filename but sets the path to the current project path...
void ClrModify()
Definition: base_screen.h:325
wxString PcbFileWildcard()
VTBL_ENTRY const wxString GetProjectPath() const
Function GetProjectPath returns the full path of the project.
Definition: project.cpp:100
PCB_SCREEN * GetScreen() const override
Function GetScreen returns a pointer to a BASE_SCREEN or one of its derivatives.
const wxSize GetPageSizeIU() const override
Function GetPageSizeIU works off of GetPageSettings() to return the size of the paper page in the int...
const wxString KiCadPcbFileExtension
Class EDA_3D_VIEWER Create and handle a window for the 3d viewer connected to a Kiway and a pcbboard...
Definition: eda_3d_viewer.h:50
void ReFillLayerWidget()
Function ReFillLayerWidget changes out all the layers in m_Layers and may be called upon loading a ne...
void Files_io_from_id(int aId)
Function Files_io_from_id Read and write board files.
void SetModify()
Definition: base_screen.h:324
Message panel definition file.
int GetDefaultCursor() const
Function GetDefaultCursor.
PCB_FILE_T
Enum PCB_FILE_T is a set of file types that the IO_MGR knows about, and for which there has been a pl...
Definition: io_mgr.h:52
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Function DisplayInfoMessage displays an informational message box with aMessage.
Definition: confirm.cpp:272
void NewDisplay(bool aForceImmediateRedraw=false)
Reload and refresh (rebuild) the 3D scene.
wxString PCadPcbFileWildcard()
EDA_3D_VIEWER * Get3DViewerFrame()
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:241
bool SavePcbFile(const wxString &aFileName, bool aCreateBackupFile=CREATE_BACKUP_FILE)
Function SavePcbFile writes the board data structures to a aFileName Creates backup when requested an...
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:47
int YesNoCancelDialog(wxWindow *aParent, const wxString &aPrimaryMessage, const wxString &aSecondaryMessage, const wxString &aYesButtonText, const wxString &aNoButtonText, const wxString &aCancelButtonText)
Function YesNoCancelDialog displays a yes/no/cancel dialog with aMessage and returns the user respons...
Definition: confirm.cpp:326
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Function IsOK displays a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:289
void ClrSave()
Definition: base_screen.h:327
void ClearMsgPanel(void)
Clear all messages from the message panel.
Definition: draw_frame.cpp:781
void ReCreateAuxiliaryToolbar() override
bool LockFile(const wxString &aFileName)
Function LockFile marks a schematic file as being in use.
Definition: draw_frame.cpp:249
virtual BOARD * Load(const wxString &aFileName, BOARD *aAppendToMe, const PROPERTIES *aProperties=NULL)
Function Load loads information from some input file format that this PLUGIN implementation knows abo...
Definition: plugin.cpp:47
S-expression Pcbnew file format.
Definition: io_mgr.h:55
static const wxString GetFileExtension(PCB_FILE_T aFileType)
Function GetFileExtension returns the file extension for aFileType.
Definition: io_mgr.cpp:117
const wxChar traceAutoSave[]
Flag to enable auto save feature debug tracing.
int m_Status_Pcb
Flags used in ratsnest calculation and update.
Definition: class_board.h:237