KiCad PCB EDA Suite
Loading...
Searching...
No Matches
import_proj.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) 2019 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#include "import_proj.h"
23#include <kidialog.h>
25#include <macros.h>
26#include <string_utils.h>
27#include <richio.h>
28
29#include <wx/fileconf.h>
30#include <wx/filedlg.h>
31#include <wx/msgdlg.h>
32#include <wx/tokenzr.h>
33#include <wx/dir.h>
34#include <wx/textfile.h>
35#include <wx/wfstream.h>
36
37#include <kiway.h>
38#include <kiway_player.h>
39#include <kicad_manager_frame.h>
40#include <pcb_edit_frame.h>
41#include <sch_edit_frame.h>
42
43#include <sch_io/sch_io_mgr.h>
44#include <pcb_io/pcb_io_mgr.h>
45#include <project_sch.h>
46#include <project_pcb.h>
47
52#include <io/pads/pads_common.h>
54
55#include <wx/log.h>
56
57
59 const std::vector<wxString>& aSchFileExtensions,
60 const std::vector<wxString>& aPcbFileExtensions ) :
61 m_frame( aFrame ),
62 m_schExtenstions( aSchFileExtensions ), m_pcbExtenstions( aPcbFileExtensions )
63{
64}
65
66
68{
69 // Append a new directory with the same name of the project file
70 // Keep iterating until we find an empty directory
71 wxString newDir = m_TargetProj.GetName();
72 int attempt = 0;
73
74 m_TargetProj.AppendDir( newDir );
75
76 while( m_TargetProj.DirExists() )
77 {
78 m_TargetProj.RemoveLastDir();
79 wxString suffix = wxString::Format( "_%d", ++attempt );
80 m_TargetProj.AppendDir( newDir + suffix );
81 }
82}
83
84
86{
87 wxString m_file;
88
89public:
90 SCOPED_FILE_REMOVER( const wxString& aFile ) : m_file( aFile ) {}
91 ~SCOPED_FILE_REMOVER() { wxRemoveFile( m_file ); }
92};
93
94
95void IMPORT_PROJ_HELPER::ImportIndividualFile( KICAD_T aFT, int aImportedFileType )
96{
97 FRAME_T frame_type;
98 wxString appImportFile;
99 std::vector<wxString> neededExts;
100
101 switch( aFT )
102 {
103 case SCHEMATIC_T:
104 neededExts = m_schExtenstions;
105 frame_type = FRAME_SCH;
106 break;
107
108 case PCB_T:
109 neededExts = m_pcbExtenstions;
110 frame_type = FRAME_PCB_EDITOR;
111 break;
112
113 default: return;
114 }
115
116 std::vector<SCOPED_FILE_REMOVER> copiedFiles;
117
118 for( wxString ext : neededExts )
119 {
120 if( ext == wxS( "INPUT" ) )
121 ext = m_InputFile.GetExt();
122
123 wxFileName candidate = m_InputFile;
124
125 // Selected file often the one wanted (e.g. schematic in schematic-only
126 // import); keep on-disk name so uppercase ext still resolves on
127 // case-sensitive fs. Rewrite ext only when seeking differently-typed sibling
128 if( m_InputFile.GetExt().CmpNoCase( ext ) != 0 )
129 candidate.SetExt( ext );
130
131 if( !candidate.FileExists() )
132 continue;
133
134 wxFileName targetFile( m_TargetProj.GetPath(), candidate.GetName(), candidate.GetExt() );
135
136 if( !targetFile.FileExists() )
137 {
138 bool copied = wxCopyFile( candidate.GetFullPath(), targetFile.GetFullPath(), false );
139
140 if( copied )
141 {
142 // Will be auto-removed
143 copiedFiles.emplace_back( targetFile.GetFullPath() );
144 }
145 }
146
147 // Pick the first file to pass to application
148 if( appImportFile.empty() && targetFile.FileExists() )
149 appImportFile = targetFile.GetFullPath();
150 }
151
152 if( appImportFile.empty() )
153 return;
154
155 doImport( appImportFile, frame_type, aImportedFileType );
156}
157
158
159void IMPORT_PROJ_HELPER::doImport( const wxString& aFile, FRAME_T aFrameType, int aImportedFileType )
160{
161 if( KIWAY_PLAYER* frame = m_frame->Kiway().Player( aFrameType, true ) )
162 {
163 std::stringstream ss;
164 ss << aImportedFileType << '\n' << TO_UTF8( aFile );
165
166 for( const auto& [key, value] : m_properties )
167 ss << '\n' << key << '\n' << value.wx_str();
168
169 std::string packet = ss.str();
170 frame->Kiway().ExpressMail( aFrameType, MAIL_IMPORT_FILE, packet, m_frame );
171
172 if( aFrameType == FRAME_SCH && aImportedFileType == SCH_IO_MGR::SCH_ORCAD
175
176 if( !frame->IsShownOnScreen() )
177 frame->Show( true );
178
179 // On Windows, Raise() does not bring the window on screen, when iconized
180 if( frame->IsIconized() )
181 frame->Iconize( false );
182
183 frame->Raise();
184 }
185}
186
187
188void IMPORT_PROJ_HELPER::EasyEDAProProjectHandler( int aImportedSchFileType, int aImportedPcbFileType )
189{
190 const bool isV3 =
191 aImportedSchFileType == SCH_IO_MGR::SCH_EASYEDAPRO_V3 || aImportedPcbFileType == PCB_IO_MGR::EASYEDAPRO_V3;
192
193 // Sch/PCB importers both assign FPIDs under ShortenLibName( archive ); advertise that
194 // nickname as the source footprint lib so post-import reconciler keeps it (instead of
195 // rewriting schematic Footprint fields onto the generated *-import-fps cache).
196 wxArrayString sourceFpLibs;
197 sourceFpLibs.Add( EASYEDAPRO::ShortenLibName( m_InputFile.GetName() ) );
199
200 nlohmann::json project;
201
202 if( isV3 )
203 {
204 // For v3, build a minimal legacy-format project from raw documents
205 EASYEDAPRO::V3_DOC_PARSER adapter( m_InputFile.GetFullPath() );
206 adapter.Load();
208 }
209 else
210 {
212 }
213
214 std::vector<IMPORT_PROJECT_DESC> toImport = EASYEDAPRO::ProjectToSelectorDialog( project, false, false );
215
216 if( toImport.size() > 1 )
217 toImport = DIALOG_IMPORT_CHOOSE_PROJECT::RunModal( m_frame, toImport );
218
219 if( toImport.size() == 1 )
220 {
221 const IMPORT_PROJECT_DESC& desc = toImport[0];
222 wxString pcbId = desc.PCBId;
223 wxString schId = desc.SchematicId;
224
225 if( pcbId.empty() && project.contains( "pcbs" ) && project.at( "pcbs" ).is_object()
226 && project.at( "pcbs" ).size() == 1 )
227 {
228 pcbId = wxString::FromUTF8( project.at( "pcbs" ).begin().key() );
229 }
230
231 if( schId.empty() && project.contains( "schematics" ) && project.at( "schematics" ).is_object()
232 && project.at( "schematics" ).size() == 1 )
233 {
234 schId = wxString::FromUTF8( project.at( "schematics" ).begin().key() );
235 }
236
237 if( !pcbId.empty() )
238 m_properties["pcb_id"] = pcbId;
239
240 if( !schId.empty() )
241 m_properties["sch_id"] = schId;
242 }
243 else
244 {
245 m_properties["pcb_id"] = "";
246 m_properties["sch_id"] = "";
247 }
248}
249
250
252{
253 // fresh empty target dir, so a stem-derived name is collision-free; reconciler still guards on-disk
254 wxString stem = m_TargetProj.GetName();
255
256 if( stem.IsEmpty() )
257 stem = m_InputFile.GetName();
258
260}
261
262
263wxString IMPORT_PROJ_HELPER::joinSourceLibNicknames( const std::set<wxString>& aPaths ) const
264{
265 wxArrayString nicks;
266
267 for( const wxString& path : aPaths )
268 {
269 wxString nick = wxFileName( path ).GetName();
270
271 if( !nick.IsEmpty() )
272 nicks.Add( nick );
273 }
274
275 return IMPORT_PROJ_PROPS::JoinList( nicks );
276}
277
278
279void IMPORT_PROJ_HELPER::addLocalLibraries( const std::set<wxString>& aNames, FRAME_T aFrameType )
280{
281 KIWAY_PLAYER* frame = m_frame->Kiway().Player( aFrameType, true );
282
283 std::stringstream ss;
284
285 // First line is the source project directory so the handler can distinguish
286 // project-local libraries from external fixed-path references.
287 ss << TO_UTF8( m_InputFile.GetPath() ) << '\n';
288
289 for( const wxString& name : aNames )
290 {
291 wxFileName fname( name );
292 fname.MakeAbsolute( m_InputFile.GetPath() );
293 ss << TO_UTF8( fname.GetFullPath() ) << '\n';
294 }
295
296 std::string packet = ss.str();
297 frame->Kiway().ExpressMail( aFrameType, MAIL_ADD_LOCAL_LIB, packet, m_frame );
298}
299
300
302{
303 wxFileConfig config( wxEmptyString, wxEmptyString, wxEmptyString, m_InputFile.GetFullPath(),
304 wxCONFIG_USE_NO_ESCAPE_CHARACTERS );
305
306 wxString groupname;
307 long groupid;
308
309 std::set<wxString> sch_file;
310 std::set<wxString> sch_libs;
311 std::set<wxString> pcb_libs;
312
313 wxString pcb_file;
314 int pcb_file_type = PCB_IO_MGR::ALTIUM_DESIGNER;
315
316 auto matchPcbExt = []( const wxString& aExt ) -> int
317 {
318 if( !aExt.CmpNoCase( wxS( "PcbDoc" ) ) )
320
321 if( !aExt.CmpNoCase( wxS( "CSPcbDoc" ) ) )
323
324 if( !aExt.CmpNoCase( wxS( "CMPcbDoc" ) ) )
326
327 if( !aExt.CmpNoCase( wxS( "SWPcbDoc" ) ) )
329
330 return -1;
331 };
332
333 for( bool more = config.GetFirstGroup( groupname, groupid ); more;
334 more = config.GetNextGroup( groupname, groupid ) )
335 {
336 if( !groupname.StartsWith( wxS( "Document" ) ) )
337 continue;
338
339 wxString number = groupname.Mid( 8 );
340 long docNumber;
341
342 if( !number.ToLong( &docNumber ) )
343 continue;
344
345 wxString path = config.Read( groupname + wxS( "/DocumentPath" ), wxEmptyString );
346
347 if( path.empty() )
348 continue;
349
350 wxFileName fname( path, wxPATH_WIN );
351
352 if( !fname.IsAbsolute() )
353 fname.MakeAbsolute( m_InputFile.GetPath() );
354
355 int pcbType = matchPcbExt( fname.GetExt() );
356
357 if( pcbType >= 0 && pcb_file.empty() )
358 {
359 pcb_file = fname.GetFullPath();
360 pcb_file_type = pcbType;
361 }
362
363 if( !fname.GetExt().CmpNoCase( "SCHDOC" ) )
364 sch_file.insert( fname.GetFullPath() );
365
366 if( !fname.GetExt().CmpNoCase( "PCBLIB" ) )
367 pcb_libs.insert( fname.GetFullPath() );
368
369 if( !fname.GetExt().CmpNoCase( "SCHLIB" ) )
370 sch_libs.insert( fname.GetFullPath() );
371 }
372
373 addLocalLibraries( sch_libs, FRAME_SCH );
375
376 // pass source fp libs to both imports so found footprints relink to source, not the cache
378
379 m_properties["project_file"] = m_InputFile.GetFullPath();
380
381 int ii = 0;
382
383 for( auto& path : sch_file )
384 {
385 std::string key = "sch" + std::to_string( ii++ );
386 m_properties[key] = path.ToStdString();
387 }
388
389 if( !sch_file.empty() )
390 doImport( "", FRAME_SCH, SCH_IO_MGR::SCH_ALTIUM );
391
392 if( !pcb_file.empty() )
393 doImport( pcb_file, FRAME_PCB_EDITOR, pcb_file_type );
394}
395
396
398{
399 m_properties.clear();
400
402
403 if( !related.HasPcb() && !related.HasSchematic() )
404 return;
405
406 std::vector<SCOPED_FILE_REMOVER> copiedFiles;
407
408 auto copyAndImport = [&]( const wxString& sourceFile, FRAME_T frameType, int fileType )
409 {
410 if( sourceFile.IsEmpty() )
411 return;
412
413 wxFileName srcFn( sourceFile );
414 wxFileName targetFile( m_TargetProj.GetPath(), srcFn.GetName(), srcFn.GetExt() );
415
416 if( !targetFile.FileExists() )
417 {
418 bool copied = wxCopyFile( srcFn.GetFullPath(), targetFile.GetFullPath(), false );
419
420 if( copied )
421 copiedFiles.emplace_back( targetFile.GetFullPath() );
422 }
423
424 if( targetFile.FileExists() )
425 doImport( targetFile.GetFullPath(), frameType, fileType );
426 };
427
428 copyAndImport( related.schematicFile, FRAME_SCH, SCH_IO_MGR::SCH_PADS );
429 copyAndImport( related.pcbFile, FRAME_PCB_EDITOR, PCB_IO_MGR::PADS );
430}
431
432
434{
435 wxFileName prjFile = m_InputFile;
436
437 if( prjFile.GetExt().CmpNoCase( "prj" ) != 0 )
438 return;
439
440 wxTextFile file;
441
442 if( !file.Open( prjFile.GetFullPath() ) )
443 {
444 wxLogWarning( _( "Could not open gEDA / Lepton EDA project file '%s'." ), prjFile.GetFullPath() );
445 return;
446 }
447
448 std::vector<wxFileName> schFiles;
449 wxString outputName;
450 wxString elementsDir;
451
452 for( size_t i = 0; i < file.GetLineCount(); ++i )
453 {
454 wxString line = file.GetLine( i );
455
456 line.Trim( true );
457 line.Trim( false );
458
459 if( line.IsEmpty() )
460 continue;
461
462 if( line.StartsWith( wxT( "#" ) ) || line.StartsWith( wxT( ";" ) ) )
463 continue;
464
465 int commentPos = line.Find( wxT( "#" ) );
466
467 if( commentPos != wxNOT_FOUND )
468 {
469 line = line.Left( commentPos );
470 line.Trim( true );
471 line.Trim( false );
472 }
473
474 if( line.IsEmpty() )
475 continue;
476
477 wxStringTokenizer tok( line );
478
479 if( !tok.HasMoreTokens() )
480 continue;
481
482 wxString keyword = tok.GetNextToken();
483
484 if( keyword.CmpNoCase( "schematics" ) == 0 )
485 {
486 while( tok.HasMoreTokens() )
487 {
488 wxString schToken = tok.GetNextToken();
489 wxFileName schFile( schToken );
490
491 if( !schFile.IsAbsolute() )
492 schFile.MakeAbsolute( prjFile.GetPath() );
493
494 schFiles.push_back( schFile );
495 }
496 }
497 else if( keyword.CmpNoCase( "output-name" ) == 0 )
498 {
499 wxString rest = line.Mid( keyword.length() );
500 rest.Trim( true );
501 rest.Trim( false );
502 outputName = rest;
503 }
504 else if( keyword.CmpNoCase( "elements-dir" ) == 0 )
505 {
506 wxString rest = line.Mid( keyword.length() );
507 rest.Trim( true );
508 rest.Trim( false );
509 elementsDir = rest;
510 }
511 }
512
513 if( !elementsDir.IsEmpty() )
514 {
515 wxFileName elementsPath( elementsDir );
516
517 if( !elementsPath.IsAbsolute() )
518 elementsPath.MakeAbsolute( prjFile.GetPath() );
519
520 m_properties["elements_dir"] = elementsPath.GetFullPath().ToStdString();
521 }
522
523 if( schFiles.empty() )
524 {
525 wxFileName candidate = prjFile;
526 candidate.SetExt( wxS( "sch" ) );
527
528 if( candidate.FileExists() )
529 schFiles.push_back( candidate );
530 }
531
532 auto promptForMissingFile =
533 [&]( const wxString& aTitle, const wxString& aWildcard, wxFileName& aFile ) -> bool
534 {
535 wxString defaultDir = aFile.GetPath();
536
537 if( defaultDir.IsEmpty() )
538 defaultDir = prjFile.GetPath();
539
540 wxFileDialog dlg( m_frame, aTitle, defaultDir, wxEmptyString, aWildcard,
541 wxFD_OPEN | wxFD_FILE_MUST_EXIST );
542
543 if( dlg.ShowModal() == wxID_OK )
544 {
545 aFile.Assign( dlg.GetPath() );
546 return true;
547 }
548
549 aFile.Clear();
550 return false;
551 };
552
553 std::vector<wxFileName> resolvedSchFiles;
554 const wxString schWildcard = _( "gEDA / Lepton EDA schematic files" ) + wxS( " (*.sch)|*.sch" );
555
556 for( wxFileName schFile : schFiles )
557 {
558 if( !schFile.FileExists() )
559 {
560 if( !promptForMissingFile( _( "Locate gEDA / Lepton EDA Schematic" ), schWildcard, schFile ) )
561 continue;
562 }
563
564 resolvedSchFiles.push_back( schFile );
565 }
566
567 if( schFiles.empty() && resolvedSchFiles.empty() )
568 {
569 wxFileName schFile;
570
571 if( promptForMissingFile( _( "Locate gEDA / Lepton EDA Schematic" ), schWildcard, schFile ) )
572 resolvedSchFiles.push_back( schFile );
573 }
574
575 if( resolvedSchFiles.size() > 1 )
576 {
577 // Pass additional schematic files as a semicolon-delimited property so the
578 // importer can create sub-sheets for each additional page within a single
579 // KiCad project hierarchy.
580 wxString additionalFiles;
581
582 for( size_t i = 1; i < resolvedSchFiles.size(); i++ )
583 {
584 if( !additionalFiles.IsEmpty() )
585 additionalFiles += wxT( ";" );
586
587 additionalFiles += resolvedSchFiles[i].GetFullPath();
588 }
589
590 m_properties["additional_schematics"] = additionalFiles.ToStdString();
591 }
592
593 // Auto-discover subdirectories containing .sym files and pass them as
594 // additional search paths for the importer's symbol resolution.
595 auto discoverSymDirs = [&]( const wxString& aBaseDir, wxString& aSymPaths )
596 {
597 wxDir dir( aBaseDir );
598
599 if( !dir.IsOpened() )
600 return;
601
602 wxString subdir;
603 bool cont = dir.GetFirst( &subdir, wxEmptyString, wxDIR_DIRS );
604
605 while( cont )
606 {
607 wxString subdirPath = aBaseDir + wxFileName::GetPathSeparator() + subdir;
608 wxDir childDir( subdirPath );
609
610 if( childDir.IsOpened() && childDir.HasFiles( wxT( "*.sym" ) ) )
611 {
612 if( !aSymPaths.IsEmpty() )
613 aSymPaths += wxT( "\n" );
614
615 aSymPaths += subdirPath;
616 }
617
618 cont = dir.GetNext( &subdir );
619 }
620 };
621
622 wxString symPaths;
623 discoverSymDirs( prjFile.GetPath(), symPaths );
624
625 if( !resolvedSchFiles.empty() )
626 {
627 wxString schDir = resolvedSchFiles[0].GetPath();
628
629 if( schDir != prjFile.GetPath() )
630 discoverSymDirs( schDir, symPaths );
631 }
632
633 if( !symPaths.IsEmpty() )
634 m_properties["sym_search_paths"] = symPaths.ToStdString();
635
636 if( !resolvedSchFiles.empty() )
637 doImport( resolvedSchFiles[0].GetFullPath(), FRAME_SCH, SCH_IO_MGR::SCH_GEDA );
638
639 wxFileName layoutDir( prjFile.GetPath(), wxEmptyString );
640 layoutDir.RemoveLastDir();
641 layoutDir.AppendDir( wxS( "layout" ) );
642
643 wxFileName pcbFile;
644
645 if( !outputName.IsEmpty() )
646 {
647 wxFileName candidate( layoutDir.GetPath(), outputName, wxS( "pcb" ) );
648
649 if( candidate.FileExists() )
650 pcbFile = candidate;
651 }
652
653 if( !pcbFile.FileExists() )
654 {
655 wxFileName candidate( prjFile.GetPath(), prjFile.GetName(), wxS( "pcb" ) );
656
657 if( candidate.FileExists() )
658 pcbFile = candidate;
659 }
660
661 if( !pcbFile.FileExists() )
662 {
663 wxFileName candidate( layoutDir.GetPath(), prjFile.GetName(), wxS( "pcb" ) );
664
665 if( candidate.FileExists() )
666 pcbFile = candidate;
667 }
668
669 const wxString pcbWildcard = _( "gEDA / Lepton EDA PCB files" ) + wxS( " (*.pcb)|*.pcb" );
670
671 if( !pcbFile.FileExists() )
672 promptForMissingFile( _( "Locate gEDA / Lepton EDA PCB" ), pcbWildcard, pcbFile );
673
674 if( pcbFile.FileExists() )
675 doImport( pcbFile.GetFullPath(), FRAME_PCB_EDITOR, PCB_IO_MGR::GEDA_PCB );
676}
677
678
679static wxFileName findSiblingByExt( const wxFileName& aBase, const wxString& aExt )
680{
681 wxDir dir( aBase.GetPath() );
682
683 if( dir.IsOpened() )
684 {
685 wxString found;
686
687 for( bool more = dir.GetFirst( &found, wxEmptyString, wxDIR_FILES ); more;
688 more = dir.GetNext( &found ) )
689 {
690 wxFileName fn( aBase.GetPath(), found );
691
692 if( fn.GetName().CmpNoCase( aBase.GetName() ) == 0 && fn.GetExt().CmpNoCase( aExt ) == 0 )
693 return fn;
694 }
695 }
696
697 return wxFileName();
698}
699
700
702{
704
705 // Import selected OrCAD Capture schematic (.dsn) first
706 ImportIndividualFile( SCHEMATIC_T, SCH_IO_MGR::SCH_ORCAD );
707
708 // Only a successful schematic import replies with a net-name map, even an empty one.
710 return;
711
712 // OrCAD designs pair w/ Cadence Allegro board; offer import, defaulting to
713 // sibling board (matched case-insensitively) next to schematic
714 wxFileName brdFile = findSiblingByExt( m_InputFile, wxS( "brd" ) );
715 bool haveSibling = brdFile.FileExists();
716
717 wxString msg = haveSibling
718 ? wxString::Format( _( "Import the associated Allegro board '%s'?" ),
719 brdFile.GetFullName() )
720 : _( "Import an associated Allegro board file?" );
721
722 KIDIALOG dlg( m_frame, msg, _( "Import Allegro Board" ), wxOK | wxCANCEL | wxICON_QUESTION );
723 dlg.SetOKCancelLabels( _( "OK" ), _( "Skip" ) );
724
725 if( dlg.ShowModal() != wxID_OK )
726 return;
727
728 if( !haveSibling )
729 {
730 wxFileDialog fileDlg( m_frame, _( "Locate Allegro Board" ), m_InputFile.GetPath(),
731 wxEmptyString, FILEEXT::AllegroPcbFilesWildcard(),
732 wxFD_OPEN | wxFD_FILE_MUST_EXIST );
733
734 if( fileDlg.ShowModal() != wxID_OK )
735 return;
736
737 brdFile.Assign( fileDlg.GetPath() );
738 }
739
740 // ExpressMail dispatches synchronously and loaded target project sets generated
741 // board path, so import source board directly, no staging copy
742 if( brdFile.FileExists() )
743 doImport( brdFile.GetFullPath(), FRAME_PCB_EDITOR, PCB_IO_MGR::ALLEGRO );
744}
745
746
747void IMPORT_PROJ_HELPER::ImportFiles( int aImportedSchFileType, int aImportedPcbFileType )
748{
749 m_properties.clear();
750
751 // both imports must agree on the cache nickname up front
753
754 int importedSchFileType = aImportedSchFileType;
755 int importedPcbFileType = aImportedPcbFileType;
756
757 if( importedSchFileType == SCH_IO_MGR::SCH_EASYEDAPRO || importedSchFileType == SCH_IO_MGR::SCH_EASYEDAPRO_V3
758 || importedPcbFileType == PCB_IO_MGR::EASYEDAPRO || importedPcbFileType == PCB_IO_MGR::EASYEDAPRO_V3 )
759 {
760 bool isV3 = EASYEDAPRO::V3_DOC_PARSER::IsV3Archive( m_InputFile.GetFullPath() );
761
762 importedSchFileType = isV3 ? SCH_IO_MGR::SCH_EASYEDAPRO_V3 : SCH_IO_MGR::SCH_EASYEDAPRO;
763 importedPcbFileType = isV3 ? PCB_IO_MGR::EASYEDAPRO_V3 : PCB_IO_MGR::EASYEDAPRO;
764
765 EasyEDAProProjectHandler( importedSchFileType, importedPcbFileType );
766 }
767 else if( importedSchFileType == SCH_IO_MGR::SCH_ALTIUM || importedPcbFileType == PCB_IO_MGR::ALTIUM_DESIGNER )
768 {
770 return;
771 }
772 else if( aImportedSchFileType == SCH_IO_MGR::SCH_ORCAD )
773 {
775 return;
776 }
777 else if( aImportedSchFileType == SCH_IO_MGR::SCH_GEDA )
778 {
779 if( m_InputFile.GetExt().CmpNoCase( "prj" ) == 0 )
780 {
782 }
783 else if( m_InputFile.GetExt().CmpNoCase( "pcb" ) == 0 )
784 {
785 ImportIndividualFile( PCB_T, aImportedPcbFileType );
786 }
787 else
788 {
789 // When importing a bare .sch file, pass the original source directory
790 // so the importer can find symbols in subdirectories relative to the
791 // gEDA / Lepton EDA schematic, even though the file may be copied to a new location
792 // for the KiCad project.
793 wxString sourceDir = m_InputFile.GetPath();
794 wxString symPaths = sourceDir;
795
796 auto discoverSymDirs = [&]( const wxString& aBaseDir )
797 {
798 wxDir dir( aBaseDir );
799
800 if( !dir.IsOpened() )
801 return;
802
803 wxString subdir;
804 bool cont = dir.GetFirst( &subdir, wxEmptyString, wxDIR_DIRS );
805
806 while( cont )
807 {
808 wxString subdirPath =
809 aBaseDir + wxFileName::GetPathSeparator() + subdir;
810 wxDir childDir( subdirPath );
811
812 if( childDir.IsOpened() && childDir.HasFiles( wxT( "*.sym" ) ) )
813 symPaths += wxT( "\n" ) + subdirPath;
814
815 cont = dir.GetNext( &subdir );
816 }
817 };
818
819 discoverSymDirs( sourceDir );
820 m_properties["sym_search_paths"] = symPaths.ToStdString();
821
822 doImport( m_InputFile.GetFullPath(), FRAME_SCH, SCH_IO_MGR::SCH_GEDA );
823 ImportIndividualFile( PCB_T, aImportedPcbFileType );
824 }
825
826 return;
827 }
828
829 ImportIndividualFile( SCHEMATIC_T, importedSchFileType );
830 ImportIndividualFile( PCB_T, importedPcbFileType );
831}
const char * name
static std::vector< IMPORT_PROJECT_DESC > RunModal(wxWindow *aParent, const std::vector< IMPORT_PROJECT_DESC > &aProjectDesc)
Create and show a dialog (modal) and returns the data from it after completion.
Parses EasyEDA Pro v3 .epro2 archives.
void Load()
Load all v3 docs from the archive.
static bool IsV3Archive(const wxString &aFileName)
Return true if aFileName looks like an EasyEDA Pro v3 archive.
void OrcadProjectHandler()
Imports the OrCAD schematic, then offers to import an associated Allegro board.
wxFileName m_TargetProj
Definition import_proj.h:63
wxString joinSourceLibNicknames(const std::set< wxString > &aPaths) const
Join the basenames of the given library paths into a source-library property value.
IMPORT_PROJ_HELPER(KICAD_MANAGER_FRAME *aframe, const std::vector< wxString > &aSchFileExtensions, const std::vector< wxString > &aPcbFileExtensions)
std::map< std::string, UTF8 > m_properties
Definition import_proj.h:68
void FindEmptyTargetDir()
Appends a new directory with the name of the project file Keep iterating until an empty directory is ...
void EasyEDAProProjectHandler(int aImportedSchFileType, int aImportedPcbFileType)
std::vector< wxString > m_pcbExtenstions
Definition import_proj.h:74
void setImportCacheNickname()
Pre-commit one collision-free generated footprint-cache nickname into m_properties so the schematic a...
KICAD_MANAGER_FRAME * m_frame
Definition import_proj.h:66
void ImportFiles(int aImportedSchFileType, int aImportedPcbFileType)
Converts imported files to kicad type files.
void addLocalLibraries(const std::set< wxString > &aLibName, FRAME_T aFrameType)
void ImportIndividualFile(KICAD_T aKicad_T, int aImportedFileType)
wxFileName m_InputFile
Definition import_proj.h:62
std::vector< wxString > m_schExtenstions
Definition import_proj.h:73
void ImportPadsFiles()
Converts PADS ASCII schematic and PCB files to KiCad type files.
void doImport(const wxString &aFile, FRAME_T aFrameType, int aImportedFileType)
The main KiCad project manager frame.
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition kidialog.h:38
bool SetOKCancelLabels(const ButtonLabel &ok, const ButtonLabel &cancel) override
Definition kidialog.h:48
int ShowModal() override
Definition kidialog.cpp:89
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
virtual void ExpressMail(FRAME_T aDestination, MAIL_T aCommand, std::string &aPayload, wxWindow *aSource=nullptr, bool aFromOtherThread=false)
Send aPayload to aDestination from aSource.
Definition kiway.cpp:486
@ GEDA_PCB
Geda PCB file formats.
Definition pcb_io_mgr.h:66
@ ALTIUM_DESIGNER
Definition pcb_io_mgr.h:59
@ ALTIUM_CIRCUIT_MAKER
Definition pcb_io_mgr.h:57
@ ALTIUM_CIRCUIT_STUDIO
Definition pcb_io_mgr.h:58
SCOPED_FILE_REMOVER(const wxString &aFile)
#define _(s)
FRAME_T
The set of EDA_BASE_FRAME derivatives, typically stored in EDA_BASE_FRAME::m_Ident.
Definition frame_type.h:29
@ FRAME_PCB_EDITOR
Definition frame_type.h:38
@ FRAME_SCH
Definition frame_type.h:30
static wxString AllegroPcbFilesWildcard()
static wxFileName findSiblingByExt(const wxFileName &aBase, const wxString &aExt)
This file contains miscellaneous commonly used macros and functions.
@ MAIL_IMPORT_FILE
Definition mail_type.h:44
@ MAIL_ADD_LOCAL_LIB
Definition mail_type.h:50
nlohmann::json BuildV3ProjectIndexFromRawDocs(const V3_DOC_PARSER &aParser, bool aIncludeLibraryMetadata=true)
Build a minimal legacy-style project index from parsed v3 raw documents.
std::vector< IMPORT_PROJECT_DESC > ProjectToSelectorDialog(const nlohmann::json &aProject, bool aPcbOnly=false, bool aSchOnly=false)
nlohmann::json ReadProjectOrDeviceFile(const wxString &aZipFileName)
wxString ShortenLibName(wxString aProjectName)
constexpr char SOURCE_FP_LIBS[]
constexpr char FP_CACHE_NICKNAME[]
wxString JoinList(const wxArrayString &aItems)
Encode library nicknames into a single list-property value.
wxString MakeCacheNickname(const wxString &aStem)
Derive the generated footprint-cache nickname from a project or file stem.
std::optional< std::map< wxString, wxString > > SplitNetNameMap(const wxString &aValue)
Decode a net-name map property value, or nothing when the value is not one.
constexpr char NET_NAME_MAP[]
RELATED_FILES FindRelatedPadsFiles(const wxString &aFilePath)
Find the related PADS project file (schematic for a PCB source, or vice versa) in the same directory,...
MODEL3D_FORMAT_TYPE fileType(const char *aFileName)
wxString From_UTF8(const char *cstring)
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Describes how non-KiCad boards and schematics should be imported as KiCad projects.
bool copied
std::string path
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:70
@ PCB_T
Definition typeinfo.h:74
@ SCHEMATIC_T
Definition typeinfo.h:200
Definition of file extensions used in Kicad.