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-2016 Wayne Stambaugh <stambaughw@verizon.net>
6  * Copyright (C) 2016 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 <wxPcbStruct.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 
46 #include <pcbnew.h>
47 #include <pcbnew_id.h>
48 #include <io_mgr.h>
50 
51 #include <class_board.h>
52 #include <build_version.h> // LEGACY_BOARD_FILE_VERSION
53 #include <module_editor_frame.h>
54 #include <modview_frame.h>
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 }, // 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 = wxGetTranslation( 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;
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;
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  wxString msg = wxString::Format( _(
524  "Error loading board.\n%s" ),
525  GetChars( ioe.What() )
526  );
527  DisplayError( this, msg );
528  return false;
529  }
530 
531  SetBoard( loadedBoard );
532 
533  // we should not ask PLUGINs to do these items:
534  loadedBoard->BuildListOfNets();
535  loadedBoard->SynchronizeNetsAndNetClasses();
536 
537  SetStatusText( wxEmptyString );
538  BestZoom();
539 
540  // update the layer names in the listbox
541  ReCreateLayerBox( false );
542 
543  GetScreen()->ClrModify();
544 
545  {
546  wxFileName fn = fullFileName;
547  CheckForAutoSaveFile( fullFileName, fn.GetExt() );
548  }
549 
550  if( pluginType == IO_MGR::LEGACY &&
551  loadedBoard->GetFileFormatVersionAtLoad() < LEGACY_BOARD_FILE_VERSION )
552  {
553  DisplayInfoMessage( this,
554  _( "This file was created by an older version of Pcbnew.\n"
555  "It will be stored in the new file format when you save this file again." ) );
556  }
557  }
558 
559  {
560  wxFileName fn = fullFileName;
561 
562  if( converted )
563  fn.SetExt( PcbFileExtension );
564 
565  wxString fname = fn.GetFullPath();
566 
567  fname.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP );
568 
569  GetBoard()->SetFileName( fname );
570  }
571 
572  UpdateTitle();
573 
574  if( !converted )
575  UpdateFileHistory( GetBoard()->GetFileName() );
576 
577  // Rebuild the new pad list (for drc and ratsnet control ...)
578  GetBoard()->m_Status_Pcb = 0;
579 
580  // Select netclass Default as current netclass (it always exists)
582 
583  // Rebuild list of nets (full ratsnest rebuild)
584  {
585  wxBusyCursor dummy; // Displays an Hourglass while building connectivity
586  Compile_Ratsnest( NULL, true );
588  }
589 
590  // Update info shown by the horizontal toolbars
593 
594  // upate the layer widget to match board visibility states, both layers and render columns.
598 
599  // Update the tracks / vias available sizes list:
601 
602  // Update the RATSNEST items, which were not loaded at the time
603  // BOARD::SetVisibleElements() was called from within any PLUGIN.
604  // See case LAYER_RATSNEST: in BOARD::SetElementVisibility()
605  GetBoard()->SetVisibleElements( GetBoard()->GetVisibleElements() );
606 
607  // Display the loaded board:
608  Zoom_Automatique( false );
609 
610  SetMsgPanel( GetBoard() );
611 
612  // Refresh the 3D view, if any
613  EDA_3D_VIEWER* draw3DFrame = Get3DViewerFrame();
614 
615  if( draw3DFrame )
616  draw3DFrame->NewDisplay();
617 
618 #if 0 && defined(DEBUG)
619  // Output the board object tree to stdout, but please run from command prompt:
620  GetBoard()->Show( 0, std::cout );
621 #endif
622 
623  // from EDA_APPL which was first loaded BOARD only:
624  {
625  /* For an obscure reason the focus is lost after loading a board file
626  * when starting up the process.
627  * (seems due to the recreation of the layer manager after loading the file)
628  * Give focus to main window and Drawpanel
629  * must be done for these 2 windows (for an obscure reason ...)
630  * Linux specific
631  * This is more a workaround than a fix.
632  */
633  SetFocus();
634  GetCanvas()->SetFocus();
635  }
636 
637  return true;
638 }
639 
640 
641 static wxString create_backup_file( const wxString& aFileName )
642 {
643  wxFileName fn = aFileName;
644  wxFileName backupFileName = aFileName;
645 
646  backupFileName.SetExt( fn.GetExt() + backupSuffix );
647 
648  // If an old backup file exists, delete it. If an old board file exists,
649  // rename it to the backup file name.
650  if( fn.FileExists() )
651  {
652  // Remove the old file xxx.000 if it exists.
653  if( backupFileName.FileExists() )
654  wxRemoveFile( backupFileName.GetFullPath() );
655 
656  // Rename the current file from <xxx>.kicad_pcb to <xxx>.kicad_pcb-bak
657  if( !wxRenameFile( fn.GetFullPath(), backupFileName.GetFullPath() ) )
658  {
659  wxString msg = wxString::Format( _(
660  "Warning: unable to create backup file '%s'" ),
661  GetChars( backupFileName.GetFullPath() )
662  );
663  DisplayError( NULL, msg );
664  }
665  }
666  else
667  {
668  backupFileName.Clear();
669  }
670 
671  return backupFileName.GetFullPath();
672 }
673 
674 
675 bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool aCreateBackupFile )
676 {
677  // please, keep it simple. prompting goes elsewhere.
678 
679  wxFileName pcbFileName = aFileName;
680 
681  if( pcbFileName.GetExt() == LegacyPcbFileExtension )
682  pcbFileName.SetExt( KiCadPcbFileExtension );
683 
684  if( !IsWritable( pcbFileName ) )
685  {
686  wxString msg = wxString::Format( _(
687  "No access rights to write to file '%s'" ),
688  GetChars( pcbFileName.GetFullPath() )
689  );
690 
691  DisplayError( this, msg );
692  return false;
693  }
694 
695  wxString backupFileName;
696 
697  // aCreateBackupFile == false is mainly used to write autosave files
698  // or new files in save as... command
699  if( aCreateBackupFile )
700  {
701  backupFileName = create_backup_file( aFileName );
702  }
703 
705 
707 
708  // Select default Netclass before writing file.
709  // Useful to save default values in headers
711 
712  ClearMsgPanel();
713 
714  wxString upperTxt;
715  wxString lowerTxt;
716 
717  try
718  {
720 
721  wxASSERT( pcbFileName.IsAbsolute() );
722 
723  pi->Save( pcbFileName.GetFullPath(), GetBoard(), NULL );
724  }
725  catch( const IO_ERROR& ioe )
726  {
727  wxString msg = wxString::Format( _(
728  "Error saving board file '%s'.\n%s" ),
729  GetChars( pcbFileName.GetFullPath() ),
730  GetChars( ioe.What() )
731  );
732  DisplayError( this, msg );
733 
734  lowerTxt.Printf( _( "Failed to create '%s'" ), GetChars( pcbFileName.GetFullPath() ) );
735 
736  AppendMsgPanel( upperTxt, lowerTxt, CYAN );
737 
738  return false;
739  }
740 
741  GetBoard()->SetFileName( pcbFileName.GetFullPath() );
742  UpdateTitle();
743 
744  // Put the saved file in File History, unless aCreateBackupFile
745  // is false.
746  // aCreateBackupFile == false is mainly used to write autosave files
747  // and not need to have an autosave file in file history
748  if( aCreateBackupFile )
749  UpdateFileHistory( GetBoard()->GetFileName() );
750 
751  // Delete auto save file on successful save.
752  wxFileName autoSaveFileName = pcbFileName;
753 
754  autoSaveFileName.SetName( wxString( autosavePrefix ) + pcbFileName.GetName() );
755 
756  if( autoSaveFileName.FileExists() )
757  wxRemoveFile( autoSaveFileName.GetFullPath() );
758 
759  if( !!backupFileName )
760  upperTxt.Printf( _( "Backup file: '%s'" ), GetChars( backupFileName ) );
761 
762  lowerTxt.Printf( _( "Wrote board file: '%s'" ), GetChars( pcbFileName.GetFullPath() ) );
763 
764  AppendMsgPanel( upperTxt, lowerTxt, CYAN );
765 
766  GetScreen()->ClrModify();
767  GetScreen()->ClrSave();
768  return true;
769 }
770 
771 
772 bool PCB_EDIT_FRAME::SavePcbCopy( const wxString& aFileName )
773 {
774  wxFileName pcbFileName = aFileName;
775 
776  // Ensure the file ext is the right ext:
777  pcbFileName.SetExt( KiCadPcbFileExtension );
778 
779  if( !IsWritable( pcbFileName ) )
780  {
781  wxString msg = wxString::Format( _(
782  "No access rights to write to file '%s'" ),
783  GetChars( pcbFileName.GetFullPath() )
784  );
785 
786  DisplayError( this, msg );
787  return false;
788  }
789 
792 
793  // Select default Netclass before writing file.
794  // Useful to save default values in headers
796 
797  try
798  {
800 
801  wxASSERT( pcbFileName.IsAbsolute() );
802 
803  pi->Save( pcbFileName.GetFullPath(), GetBoard(), NULL );
804  }
805  catch( const IO_ERROR& ioe )
806  {
807  wxString msg = wxString::Format( _(
808  "Error saving board file '%s'.\n%s" ),
809  GetChars( pcbFileName.GetFullPath() ),
810  GetChars( ioe.What() )
811  );
812  DisplayError( this, msg );
813 
814  return false;
815  }
816 
817  DisplayInfoMessage( this, wxString::Format( _( "Board copied to:\n'%s'" ),
818  GetChars( pcbFileName.GetFullPath() ) ) );
819 
820  return true;
821 }
822 
823 
825 {
826  wxFileName tmpFileName;
827 
828  if( GetBoard()->GetFileName().IsEmpty() )
829  {
830  tmpFileName = wxFileName( wxStandardPaths::Get().GetDocumentsDir(), wxT( "noname" ),
832  GetBoard()->SetFileName( tmpFileName.GetFullPath() );
833  }
834  else
835  {
836  tmpFileName = Prj().AbsolutePath( GetBoard()->GetFileName() );
837  }
838 
839  wxFileName autoSaveFileName = tmpFileName;
840 
841  // Auto save file name is the board file name prepended with autosaveFilePrefix string.
842  autoSaveFileName.SetName( wxString( autosavePrefix ) + autoSaveFileName.GetName() );
843 
844  if( !autoSaveFileName.IsOk() )
845  return false;
846 
847  // If the board file path is not writable, try writing to a platform specific temp file
848  // path. If that path isn't writabe, give up.
849  if( !autoSaveFileName.IsDirWritable() )
850  {
851  autoSaveFileName.SetPath( wxFileName::GetTempDir() );
852 
853  if( !autoSaveFileName.IsOk() || !autoSaveFileName.IsDirWritable() )
854  return false;
855  }
856 
857  wxLogTrace( traceAutoSave, "Creating auto save file <" + autoSaveFileName.GetFullPath() + ">" );
858 
859  if( SavePcbFile( autoSaveFileName.GetFullPath(), NO_BACKUP_FILE ) )
860  {
861  GetScreen()->SetModify();
862  GetBoard()->SetFileName( tmpFileName.GetFullPath() );
863  UpdateTitle();
864  m_autoSaveState = false;
865  return true;
866  }
867 
868  GetBoard()->SetFileName( tmpFileName.GetFullPath() );
869 
870  return false;
871 }
void syncRenderStates()
Function syncRenderStates updates the "Render" checkboxes in the layer widget according to current to...
Definition: pcbframe.cpp:909
void CheckForAutoSaveFile(const wxFileName &aFileName, const wxString &aBackupFileExtension)
Function CheckForAutoSaveFile checks if an auto save file exists for aFileName and takes the appropri...
Definition: basicframe.cpp:576
void UpdateTitle()
Function UpdateTitle sets the main window title bar text.
Definition: pcbframe.cpp:1024
Class UTF8 is an 8 bit std::string that is assuredly encoded in UTF8, and supplies special conversion...
Definition: utf8.h:53
#define DIM(x)
of elements in an array
Definition: macros.h:98
bool m_autoSaveState
Flag to indicate the last auto save state.
Definition: wxstruct.h:145
void BuildListOfNets()
Definition: class_board.h:764
virtual void OnModify() override
Function OnModify must be called after a board change to set the modified flag.
Definition: pcbframe.cpp:996
Definition of class FOOTPRINT_EDIT_FRAME.
const wxChar traceAutoSave[]
Custom trace mask to enable and disable auto save tracing.
Definition: basicframe.cpp:53
#define WIN_STRING_DIR_SEP
Definition: gestfich.h:44
void syncLayerWidgetLayer()
Function syncLayerWidgetLayer updates the currently layer "selection" within the PCB_LAYER_WIDGET.
Definition: pcbframe.cpp:902
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.
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
Definition: draw_panel.cpp:326
void SetVisibleElements(int aMask)
Function SetVisibleElements is a proxy function that calls the correspondent function in m_BoardSetti...
This file is part of the common library.
const wxString EaglePcbFileWildcard
EDA_DRAW_PANEL * GetCanvas()
Definition: draw_frame.h:299
const wxString ProjectFileExtension
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)
#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.
Class that computes missing connections on a PCB.
bool Clear_Pcb(bool aQuery)
Function Clear_Pcb delete all and reinitialize the current board.
Definition: initpcb.cpp:39
#define NO_BACKUP_FILE
Definition: wxstruct.h:60
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'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 ...
Definition: tool_pcb.cpp:709
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...
Definition: pcbframe.cpp:915
bool IsWritable(const wxFileName &aFileName)
Function IsWritable checks if aFileName can be written.
Definition: basicframe.cpp:532
bool SetCurrentNetClass(const wxString &aNetClassName)
Function SetCurrentNetClass Must be called after a netclass selection (or after a netclass parameter ...
Definition: pcbframe.cpp:1115
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.
Definition: basicframe.cpp:388
const wxString LegacyPcbFileWildcard
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:75
Class RELEASER releases a PLUGIN in the context of a potential thrown exception, through its destruct...
Definition: io_mgr.h:476
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 ...
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:77
const wxString PCadPcbFileWildcard
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:754
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
#define PcbFileExtension
S-expression Pcbnew file format.
Definition: io_mgr.h:54
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
void ProcessBoard()
Function ProcessBoard() Prepares data for computing (computes a list of current nodes and connections...
VTBL_ENTRY const wxString AbsolutePath(const wxString &aFileName) const
Function AbsolutePath fixes up aFileName if it is relative to the project's directory to be an absolu...
Definition: project.cpp:371
The common library.
static const wxChar backupSuffix[]
void SetFileName(const wxString &aFileName)
Definition: class_board.h:235
static const struct @16 fileFilters[FILTER_COUNT]
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:65
RN_DATA * GetRatsnest() const
Function GetRatsnest() returns list of missing connections between components/tracks.
Definition: class_board.h:287
int GetFileFormatVersionAtLoad() const
Definition: class_board.h:272
virtual double BestZoom() override
Function BestZoom.
void Compile_Ratsnest(wxDC *aDC, bool aDisplayStatus)
Function Compile_Ratsnest Create the entire board ratsnest.
Definition: ratsnest.cpp:165
static const wxChar autosavePrefix[]
EDA_DRAW_PANEL * m_canvas
The area to draw on.
Definition: draw_frame.h:92
void AppendMsgPanel(const wxString &textUpper, const wxString &textLower, COLOR4D color, int pad=6)
Append a message to the message panel.
Definition: draw_frame.cpp:734
void DisplayInfoMessage(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayInfoMessage displays an informational message box with aMessage.
Definition: confirm.cpp:89
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:53
see class PGM_BASE
void SetBoard(BOARD *aBoard) override
>
Definition: pcbframe.cpp:506
Declaration of the eda_3d_viewer class.
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
static LIB_PART * dummy()
Used when a LIB_PART is not found in library to draw a dummy shape This component is a 400 mils squar...
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:166
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
const wxString LegacyPcbFileExtension
#define CREATE_BACKUP_FILE
Definition: wxstruct.h:59
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.
Definition: basicframe.cpp:400
const wxString KiCadPcbFileExtension
PCB_SCREEN * GetScreen() const override
Function GetScreen returns a pointer to a BASE_SCREEN or one of its derivatives.
const char * name
const wxSize GetPageSizeIU() const override
Function GetPageSizeIU works off of GetPageSettings() to return the size of the paper page in the int...
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...
Definition: pcbframe.cpp:581
void Files_io_from_id(int aId)
Function Files_io_from_id Read and write board files.
Message panel definition file.
int GetDefaultCursor() const
Function GetDefaultCursor return the default cursor shape.
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:51
void NewDisplay(bool aForceImmediateRedraw=false)
Reload and refresh (rebuild) the 3D scene.
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:69
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:148
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Function IsOK displays a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:111
void ClearMsgPanel(void)
Clear all messages from the message panel.
Definition: draw_frame.cpp:745
void ReCreateAuxiliaryToolbar() override
Definition: tool_pcb.cpp:541
const wxString PcbFileWildcard
bool LockFile(const wxString &aFileName)
Function LockFile marks a schematic file as being in use.
Definition: draw_frame.cpp:235
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
static const wxString GetFileExtension(PCB_FILE_T aFileType)
Function GetFileExtension returns the file extension for aFileType.
Definition: io_mgr.cpp:167
int m_Status_Pcb
Flags used in ratsnest calculation and update.
Definition: class_board.h:240