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( !frame->IsShownOnScreen() )
173 frame->Show( true );
174
175 // On Windows, Raise() does not bring the window on screen, when iconized
176 if( frame->IsIconized() )
177 frame->Iconize( false );
178
179 frame->Raise();
180 }
181}
182
183
184void IMPORT_PROJ_HELPER::EasyEDAProProjectHandler( int aImportedSchFileType, int aImportedPcbFileType )
185{
186 const bool isV3 =
187 aImportedSchFileType == SCH_IO_MGR::SCH_EASYEDAPRO_V3 || aImportedPcbFileType == PCB_IO_MGR::EASYEDAPRO_V3;
188
189 // Sch/PCB importers both assign FPIDs under ShortenLibName( archive ); advertise that
190 // nickname as the source footprint lib so post-import reconciler keeps it (instead of
191 // rewriting schematic Footprint fields onto the generated *-import-fps cache).
192 wxArrayString sourceFpLibs;
193 sourceFpLibs.Add( EASYEDAPRO::ShortenLibName( m_InputFile.GetName() ) );
195
196 nlohmann::json project;
197
198 if( isV3 )
199 {
200 // For v3, build a minimal legacy-format project from raw documents
201 EASYEDAPRO::V3_DOC_PARSER adapter( m_InputFile.GetFullPath() );
202 adapter.Load();
204 }
205 else
206 {
208 }
209
210 std::vector<IMPORT_PROJECT_DESC> toImport = EASYEDAPRO::ProjectToSelectorDialog( project, false, false );
211
212 if( toImport.size() > 1 )
213 toImport = DIALOG_IMPORT_CHOOSE_PROJECT::RunModal( m_frame, toImport );
214
215 if( toImport.size() == 1 )
216 {
217 const IMPORT_PROJECT_DESC& desc = toImport[0];
218 wxString pcbId = desc.PCBId;
219 wxString schId = desc.SchematicId;
220
221 if( pcbId.empty() && project.contains( "pcbs" ) && project.at( "pcbs" ).is_object()
222 && project.at( "pcbs" ).size() == 1 )
223 {
224 pcbId = wxString::FromUTF8( project.at( "pcbs" ).begin().key() );
225 }
226
227 if( schId.empty() && project.contains( "schematics" ) && project.at( "schematics" ).is_object()
228 && project.at( "schematics" ).size() == 1 )
229 {
230 schId = wxString::FromUTF8( project.at( "schematics" ).begin().key() );
231 }
232
233 if( !pcbId.empty() )
234 m_properties["pcb_id"] = pcbId;
235
236 if( !schId.empty() )
237 m_properties["sch_id"] = schId;
238 }
239 else
240 {
241 m_properties["pcb_id"] = "";
242 m_properties["sch_id"] = "";
243 }
244}
245
246
248{
249 // fresh empty target dir, so a stem-derived name is collision-free; reconciler still guards on-disk
250 wxString stem = m_TargetProj.GetName();
251
252 if( stem.IsEmpty() )
253 stem = m_InputFile.GetName();
254
256}
257
258
259wxString IMPORT_PROJ_HELPER::joinSourceLibNicknames( const std::set<wxString>& aPaths ) const
260{
261 wxArrayString nicks;
262
263 for( const wxString& path : aPaths )
264 {
265 wxString nick = wxFileName( path ).GetName();
266
267 if( !nick.IsEmpty() )
268 nicks.Add( nick );
269 }
270
271 return IMPORT_PROJ_PROPS::JoinList( nicks );
272}
273
274
275void IMPORT_PROJ_HELPER::addLocalLibraries( const std::set<wxString>& aNames, FRAME_T aFrameType )
276{
277 KIWAY_PLAYER* frame = m_frame->Kiway().Player( aFrameType, true );
278
279 std::stringstream ss;
280
281 // First line is the source project directory so the handler can distinguish
282 // project-local libraries from external fixed-path references.
283 ss << TO_UTF8( m_InputFile.GetPath() ) << '\n';
284
285 for( const wxString& name : aNames )
286 {
287 wxFileName fname( name );
288 fname.MakeAbsolute( m_InputFile.GetPath() );
289 ss << TO_UTF8( fname.GetFullPath() ) << '\n';
290 }
291
292 std::string packet = ss.str();
293 frame->Kiway().ExpressMail( aFrameType, MAIL_ADD_LOCAL_LIB, packet, m_frame );
294}
295
296
298{
299 wxFileConfig config( wxEmptyString, wxEmptyString, wxEmptyString, m_InputFile.GetFullPath(),
300 wxCONFIG_USE_NO_ESCAPE_CHARACTERS );
301
302 wxString groupname;
303 long groupid;
304
305 std::set<wxString> sch_file;
306 std::set<wxString> sch_libs;
307 std::set<wxString> pcb_libs;
308
309 wxString pcb_file;
310 int pcb_file_type = PCB_IO_MGR::ALTIUM_DESIGNER;
311
312 auto matchPcbExt = []( const wxString& aExt ) -> int
313 {
314 if( !aExt.CmpNoCase( wxS( "PcbDoc" ) ) )
316
317 if( !aExt.CmpNoCase( wxS( "CSPcbDoc" ) ) )
319
320 if( !aExt.CmpNoCase( wxS( "CMPcbDoc" ) ) )
322
323 if( !aExt.CmpNoCase( wxS( "SWPcbDoc" ) ) )
325
326 return -1;
327 };
328
329 for( bool more = config.GetFirstGroup( groupname, groupid ); more;
330 more = config.GetNextGroup( groupname, groupid ) )
331 {
332 if( !groupname.StartsWith( wxS( "Document" ) ) )
333 continue;
334
335 wxString number = groupname.Mid( 8 );
336 long docNumber;
337
338 if( !number.ToLong( &docNumber ) )
339 continue;
340
341 wxString path = config.Read( groupname + wxS( "/DocumentPath" ), wxEmptyString );
342
343 if( path.empty() )
344 continue;
345
346 wxFileName fname( path, wxPATH_WIN );
347
348 if( !fname.IsAbsolute() )
349 fname.MakeAbsolute( m_InputFile.GetPath() );
350
351 int pcbType = matchPcbExt( fname.GetExt() );
352
353 if( pcbType >= 0 && pcb_file.empty() )
354 {
355 pcb_file = fname.GetFullPath();
356 pcb_file_type = pcbType;
357 }
358
359 if( !fname.GetExt().CmpNoCase( "SCHDOC" ) )
360 sch_file.insert( fname.GetFullPath() );
361
362 if( !fname.GetExt().CmpNoCase( "PCBLIB" ) )
363 pcb_libs.insert( fname.GetFullPath() );
364
365 if( !fname.GetExt().CmpNoCase( "SCHLIB" ) )
366 sch_libs.insert( fname.GetFullPath() );
367 }
368
369 addLocalLibraries( sch_libs, FRAME_SCH );
371
372 // pass source fp libs to both imports so found footprints relink to source, not the cache
374
375 m_properties["project_file"] = m_InputFile.GetFullPath();
376
377 int ii = 0;
378
379 for( auto& path : sch_file )
380 {
381 std::string key = "sch" + std::to_string( ii++ );
382 m_properties[key] = path.ToStdString();
383 }
384
385 if( !sch_file.empty() )
386 doImport( "", FRAME_SCH, SCH_IO_MGR::SCH_ALTIUM );
387
388 if( !pcb_file.empty() )
389 doImport( pcb_file, FRAME_PCB_EDITOR, pcb_file_type );
390}
391
392
394{
395 m_properties.clear();
396
398
399 if( !related.HasPcb() && !related.HasSchematic() )
400 return;
401
402 std::vector<SCOPED_FILE_REMOVER> copiedFiles;
403
404 auto copyAndImport = [&]( const wxString& sourceFile, FRAME_T frameType, int fileType )
405 {
406 if( sourceFile.IsEmpty() )
407 return;
408
409 wxFileName srcFn( sourceFile );
410 wxFileName targetFile( m_TargetProj.GetPath(), srcFn.GetName(), srcFn.GetExt() );
411
412 if( !targetFile.FileExists() )
413 {
414 bool copied = wxCopyFile( srcFn.GetFullPath(), targetFile.GetFullPath(), false );
415
416 if( copied )
417 copiedFiles.emplace_back( targetFile.GetFullPath() );
418 }
419
420 if( targetFile.FileExists() )
421 doImport( targetFile.GetFullPath(), frameType, fileType );
422 };
423
424 copyAndImport( related.schematicFile, FRAME_SCH, SCH_IO_MGR::SCH_PADS );
425 copyAndImport( related.pcbFile, FRAME_PCB_EDITOR, PCB_IO_MGR::PADS );
426}
427
428
430{
431 wxFileName prjFile = m_InputFile;
432
433 if( prjFile.GetExt().CmpNoCase( "prj" ) != 0 )
434 return;
435
436 wxTextFile file;
437
438 if( !file.Open( prjFile.GetFullPath() ) )
439 {
440 wxLogWarning( _( "Could not open gEDA / Lepton EDA project file '%s'." ), prjFile.GetFullPath() );
441 return;
442 }
443
444 std::vector<wxFileName> schFiles;
445 wxString outputName;
446 wxString elementsDir;
447
448 for( size_t i = 0; i < file.GetLineCount(); ++i )
449 {
450 wxString line = file.GetLine( i );
451
452 line.Trim( true );
453 line.Trim( false );
454
455 if( line.IsEmpty() )
456 continue;
457
458 if( line.StartsWith( wxT( "#" ) ) || line.StartsWith( wxT( ";" ) ) )
459 continue;
460
461 int commentPos = line.Find( wxT( "#" ) );
462
463 if( commentPos != wxNOT_FOUND )
464 {
465 line = line.Left( commentPos );
466 line.Trim( true );
467 line.Trim( false );
468 }
469
470 if( line.IsEmpty() )
471 continue;
472
473 wxStringTokenizer tok( line );
474
475 if( !tok.HasMoreTokens() )
476 continue;
477
478 wxString keyword = tok.GetNextToken();
479
480 if( keyword.CmpNoCase( "schematics" ) == 0 )
481 {
482 while( tok.HasMoreTokens() )
483 {
484 wxString schToken = tok.GetNextToken();
485 wxFileName schFile( schToken );
486
487 if( !schFile.IsAbsolute() )
488 schFile.MakeAbsolute( prjFile.GetPath() );
489
490 schFiles.push_back( schFile );
491 }
492 }
493 else if( keyword.CmpNoCase( "output-name" ) == 0 )
494 {
495 wxString rest = line.Mid( keyword.length() );
496 rest.Trim( true );
497 rest.Trim( false );
498 outputName = rest;
499 }
500 else if( keyword.CmpNoCase( "elements-dir" ) == 0 )
501 {
502 wxString rest = line.Mid( keyword.length() );
503 rest.Trim( true );
504 rest.Trim( false );
505 elementsDir = rest;
506 }
507 }
508
509 if( !elementsDir.IsEmpty() )
510 {
511 wxFileName elementsPath( elementsDir );
512
513 if( !elementsPath.IsAbsolute() )
514 elementsPath.MakeAbsolute( prjFile.GetPath() );
515
516 m_properties["elements_dir"] = elementsPath.GetFullPath().ToStdString();
517 }
518
519 if( schFiles.empty() )
520 {
521 wxFileName candidate = prjFile;
522 candidate.SetExt( wxS( "sch" ) );
523
524 if( candidate.FileExists() )
525 schFiles.push_back( candidate );
526 }
527
528 auto promptForMissingFile =
529 [&]( const wxString& aTitle, const wxString& aWildcard, wxFileName& aFile ) -> bool
530 {
531 wxString defaultDir = aFile.GetPath();
532
533 if( defaultDir.IsEmpty() )
534 defaultDir = prjFile.GetPath();
535
536 wxFileDialog dlg( m_frame, aTitle, defaultDir, wxEmptyString, aWildcard,
537 wxFD_OPEN | wxFD_FILE_MUST_EXIST );
538
539 if( dlg.ShowModal() == wxID_OK )
540 {
541 aFile.Assign( dlg.GetPath() );
542 return true;
543 }
544
545 aFile.Clear();
546 return false;
547 };
548
549 std::vector<wxFileName> resolvedSchFiles;
550 const wxString schWildcard = _( "gEDA / Lepton EDA schematic files" ) + wxS( " (*.sch)|*.sch" );
551
552 for( wxFileName schFile : schFiles )
553 {
554 if( !schFile.FileExists() )
555 {
556 if( !promptForMissingFile( _( "Locate gEDA / Lepton EDA Schematic" ), schWildcard, schFile ) )
557 continue;
558 }
559
560 resolvedSchFiles.push_back( schFile );
561 }
562
563 if( schFiles.empty() && resolvedSchFiles.empty() )
564 {
565 wxFileName schFile;
566
567 if( promptForMissingFile( _( "Locate gEDA / Lepton EDA Schematic" ), schWildcard, schFile ) )
568 resolvedSchFiles.push_back( schFile );
569 }
570
571 if( resolvedSchFiles.size() > 1 )
572 {
573 // Pass additional schematic files as a semicolon-delimited property so the
574 // importer can create sub-sheets for each additional page within a single
575 // KiCad project hierarchy.
576 wxString additionalFiles;
577
578 for( size_t i = 1; i < resolvedSchFiles.size(); i++ )
579 {
580 if( !additionalFiles.IsEmpty() )
581 additionalFiles += wxT( ";" );
582
583 additionalFiles += resolvedSchFiles[i].GetFullPath();
584 }
585
586 m_properties["additional_schematics"] = additionalFiles.ToStdString();
587 }
588
589 // Auto-discover subdirectories containing .sym files and pass them as
590 // additional search paths for the importer's symbol resolution.
591 auto discoverSymDirs = [&]( const wxString& aBaseDir, wxString& aSymPaths )
592 {
593 wxDir dir( aBaseDir );
594
595 if( !dir.IsOpened() )
596 return;
597
598 wxString subdir;
599 bool cont = dir.GetFirst( &subdir, wxEmptyString, wxDIR_DIRS );
600
601 while( cont )
602 {
603 wxString subdirPath = aBaseDir + wxFileName::GetPathSeparator() + subdir;
604 wxDir childDir( subdirPath );
605
606 if( childDir.IsOpened() && childDir.HasFiles( wxT( "*.sym" ) ) )
607 {
608 if( !aSymPaths.IsEmpty() )
609 aSymPaths += wxT( "\n" );
610
611 aSymPaths += subdirPath;
612 }
613
614 cont = dir.GetNext( &subdir );
615 }
616 };
617
618 wxString symPaths;
619 discoverSymDirs( prjFile.GetPath(), symPaths );
620
621 if( !resolvedSchFiles.empty() )
622 {
623 wxString schDir = resolvedSchFiles[0].GetPath();
624
625 if( schDir != prjFile.GetPath() )
626 discoverSymDirs( schDir, symPaths );
627 }
628
629 if( !symPaths.IsEmpty() )
630 m_properties["sym_search_paths"] = symPaths.ToStdString();
631
632 if( !resolvedSchFiles.empty() )
633 doImport( resolvedSchFiles[0].GetFullPath(), FRAME_SCH, SCH_IO_MGR::SCH_GEDA );
634
635 wxFileName layoutDir( prjFile.GetPath(), wxEmptyString );
636 layoutDir.RemoveLastDir();
637 layoutDir.AppendDir( wxS( "layout" ) );
638
639 wxFileName pcbFile;
640
641 if( !outputName.IsEmpty() )
642 {
643 wxFileName candidate( layoutDir.GetPath(), outputName, wxS( "pcb" ) );
644
645 if( candidate.FileExists() )
646 pcbFile = candidate;
647 }
648
649 if( !pcbFile.FileExists() )
650 {
651 wxFileName candidate( prjFile.GetPath(), prjFile.GetName(), wxS( "pcb" ) );
652
653 if( candidate.FileExists() )
654 pcbFile = candidate;
655 }
656
657 if( !pcbFile.FileExists() )
658 {
659 wxFileName candidate( layoutDir.GetPath(), prjFile.GetName(), wxS( "pcb" ) );
660
661 if( candidate.FileExists() )
662 pcbFile = candidate;
663 }
664
665 const wxString pcbWildcard = _( "gEDA / Lepton EDA PCB files" ) + wxS( " (*.pcb)|*.pcb" );
666
667 if( !pcbFile.FileExists() )
668 promptForMissingFile( _( "Locate gEDA / Lepton EDA PCB" ), pcbWildcard, pcbFile );
669
670 if( pcbFile.FileExists() )
671 doImport( pcbFile.GetFullPath(), FRAME_PCB_EDITOR, PCB_IO_MGR::GEDA_PCB );
672}
673
674
675static wxFileName findSiblingByExt( const wxFileName& aBase, const wxString& aExt )
676{
677 wxDir dir( aBase.GetPath() );
678
679 if( dir.IsOpened() )
680 {
681 wxString found;
682
683 for( bool more = dir.GetFirst( &found, wxEmptyString, wxDIR_FILES ); more;
684 more = dir.GetNext( &found ) )
685 {
686 wxFileName fn( aBase.GetPath(), found );
687
688 if( fn.GetName().CmpNoCase( aBase.GetName() ) == 0 && fn.GetExt().CmpNoCase( aExt ) == 0 )
689 return fn;
690 }
691 }
692
693 return wxFileName();
694}
695
696
698{
699 // Import selected OrCAD Capture schematic (.dsn) first
700 ImportIndividualFile( SCHEMATIC_T, SCH_IO_MGR::SCH_ORCAD );
701
702 // OrCAD designs pair w/ Cadence Allegro board; offer import, defaulting to
703 // sibling board (matched case-insensitively) next to schematic
704 wxFileName brdFile = findSiblingByExt( m_InputFile, wxS( "brd" ) );
705 bool haveSibling = brdFile.FileExists();
706
707 wxString msg = haveSibling
708 ? wxString::Format( _( "Import the associated Allegro board '%s'?" ),
709 brdFile.GetFullName() )
710 : _( "Import an associated Allegro board file?" );
711
712 KIDIALOG dlg( m_frame, msg, _( "Import Allegro Board" ), wxOK | wxCANCEL | wxICON_QUESTION );
713 dlg.SetOKCancelLabels( _( "OK" ), _( "Skip" ) );
714
715 if( dlg.ShowModal() != wxID_OK )
716 return;
717
718 if( !haveSibling )
719 {
720 wxFileDialog fileDlg( m_frame, _( "Locate Allegro Board" ), m_InputFile.GetPath(),
721 wxEmptyString, FILEEXT::AllegroPcbFilesWildcard(),
722 wxFD_OPEN | wxFD_FILE_MUST_EXIST );
723
724 if( fileDlg.ShowModal() != wxID_OK )
725 return;
726
727 brdFile.Assign( fileDlg.GetPath() );
728 }
729
730 // ExpressMail dispatches synchronously and loaded target project sets generated
731 // board path, so import source board directly, no staging copy
732 if( brdFile.FileExists() )
733 doImport( brdFile.GetFullPath(), FRAME_PCB_EDITOR, PCB_IO_MGR::ALLEGRO );
734}
735
736
737void IMPORT_PROJ_HELPER::ImportFiles( int aImportedSchFileType, int aImportedPcbFileType )
738{
739 m_properties.clear();
740
741 // both imports must agree on the cache nickname up front
743
744 int importedSchFileType = aImportedSchFileType;
745 int importedPcbFileType = aImportedPcbFileType;
746
747 if( importedSchFileType == SCH_IO_MGR::SCH_EASYEDAPRO || importedSchFileType == SCH_IO_MGR::SCH_EASYEDAPRO_V3
748 || importedPcbFileType == PCB_IO_MGR::EASYEDAPRO || importedPcbFileType == PCB_IO_MGR::EASYEDAPRO_V3 )
749 {
750 bool isV3 = EASYEDAPRO::V3_DOC_PARSER::IsV3Archive( m_InputFile.GetFullPath() );
751
752 importedSchFileType = isV3 ? SCH_IO_MGR::SCH_EASYEDAPRO_V3 : SCH_IO_MGR::SCH_EASYEDAPRO;
753 importedPcbFileType = isV3 ? PCB_IO_MGR::EASYEDAPRO_V3 : PCB_IO_MGR::EASYEDAPRO;
754
755 EasyEDAProProjectHandler( importedSchFileType, importedPcbFileType );
756 }
757 else if( importedSchFileType == SCH_IO_MGR::SCH_ALTIUM || importedPcbFileType == PCB_IO_MGR::ALTIUM_DESIGNER )
758 {
760 return;
761 }
762 else if( aImportedSchFileType == SCH_IO_MGR::SCH_ORCAD )
763 {
765 return;
766 }
767 else if( aImportedSchFileType == SCH_IO_MGR::SCH_GEDA )
768 {
769 if( m_InputFile.GetExt().CmpNoCase( "prj" ) == 0 )
770 {
772 }
773 else if( m_InputFile.GetExt().CmpNoCase( "pcb" ) == 0 )
774 {
775 ImportIndividualFile( PCB_T, aImportedPcbFileType );
776 }
777 else
778 {
779 // When importing a bare .sch file, pass the original source directory
780 // so the importer can find symbols in subdirectories relative to the
781 // gEDA / Lepton EDA schematic, even though the file may be copied to a new location
782 // for the KiCad project.
783 wxString sourceDir = m_InputFile.GetPath();
784 wxString symPaths = sourceDir;
785
786 auto discoverSymDirs = [&]( const wxString& aBaseDir )
787 {
788 wxDir dir( aBaseDir );
789
790 if( !dir.IsOpened() )
791 return;
792
793 wxString subdir;
794 bool cont = dir.GetFirst( &subdir, wxEmptyString, wxDIR_DIRS );
795
796 while( cont )
797 {
798 wxString subdirPath =
799 aBaseDir + wxFileName::GetPathSeparator() + subdir;
800 wxDir childDir( subdirPath );
801
802 if( childDir.IsOpened() && childDir.HasFiles( wxT( "*.sym" ) ) )
803 symPaths += wxT( "\n" ) + subdirPath;
804
805 cont = dir.GetNext( &subdir );
806 }
807 };
808
809 discoverSymDirs( sourceDir );
810 m_properties["sym_search_paths"] = symPaths.ToStdString();
811
812 doImport( m_InputFile.GetFullPath(), FRAME_SCH, SCH_IO_MGR::SCH_GEDA );
813 ImportIndividualFile( PCB_T, aImportedPcbFileType );
814 }
815
816 return;
817 }
818
819 ImportIndividualFile( SCHEMATIC_T, importedSchFileType );
820 ImportIndividualFile( PCB_T, importedPcbFileType );
821}
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:45
@ MAIL_ADD_LOCAL_LIB
Definition mail_type.h:51
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.
RELATED_FILES FindRelatedPadsFiles(const wxString &aFilePath)
Find related PADS project files from a given source file.
Common utilities and types for parsing PADS file formats.
MODEL3D_FORMAT_TYPE fileType(const char *aFileName)
#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.
Result of detecting related PADS project files.
Definition pads_common.h:74
wxString schematicFile
Path to schematic file if found.
Definition pads_common.h:76
wxString pcbFile
Path to PCB file if found.
Definition pads_common.h:75
bool copied
std::string path
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:71
@ PCB_T
Definition typeinfo.h:75
@ SCHEMATIC_T
Definition typeinfo.h:201
Definition of file extensions used in Kicad.