You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

228 lines
6.2 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2007-2017 Jean-Pierre Charras jp.charras at wanadoo.fr
  5. * Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 2
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU 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, you may find one here:
  19. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  20. * or you may search the http://www.gnu.org website for the version 2 license,
  21. * or you may write to the Free Software Foundation, Inc.,
  22. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  23. */
  24. /**
  25. * @file job_file_reader.cpp
  26. */
  27. #include <fctsys.h>
  28. #include <wx/filename.h>
  29. #include <wildcards_and_files_ext.h>
  30. #include <gerbview.h>
  31. #include <richio.h>
  32. #include <class_drawpanel.h>
  33. #include <gerber_file_image.h>
  34. #include <gerber_file_image_list.h>
  35. #include <gerbview_frame.h>
  36. #include <reporter.h>
  37. #include <gbr_metadata.h>
  38. #include <html_messagebox.h>
  39. #include <view/view.h>
  40. #include "json11.hpp" // A light JSON parser
  41. /**
  42. * this class read and parse a Gerber job file to extract useful info
  43. * for GerbView
  44. *
  45. * In a gerber job file, old (deprecated) format, data lines start by
  46. * %TF. (usual Gerber X2 info)
  47. * %TJ.B. (board info)
  48. * %TJ.D. (design info)
  49. * %TJ.L. (layers info)
  50. * some others are not yet handled by Kicad
  51. * M02* is the last line
  52. * In a gerber job file, JSON format, first lines are
  53. * {
  54. * "Header":
  55. * and the block ( a JSON array) containing the filename of files to load is
  56. * "FilesAttributes":
  57. * [
  58. * {
  59. * "Path": "interf_u-Composant.gbr",
  60. * "FileFunction": "Copper,L1,Top",
  61. * "FilePolarity": "Positive"
  62. * },
  63. * {
  64. * "Path": "interf_u-In1.Cu.gbr",
  65. * "FileFunction": "Copper,L2,Inr",
  66. * "FilePolarity": "Positive"
  67. * },
  68. * ],
  69. */
  70. class GERBER_JOBFILE_READER
  71. {
  72. public:
  73. GERBER_JOBFILE_READER( const wxString& aFileName, REPORTER* aReporter )
  74. {
  75. m_filename = aFileName;
  76. m_reporter = aReporter;
  77. }
  78. ~GERBER_JOBFILE_READER() {}
  79. bool ReadGerberJobFile(); /// read a .gbrjob file
  80. wxArrayString& GetGerberFiles() { return m_GerberFiles; }
  81. private:
  82. REPORTER* m_reporter;
  83. wxFileName m_filename;
  84. wxArrayString m_GerberFiles; // List of gerber files in job
  85. };
  86. bool GERBER_JOBFILE_READER::ReadGerberJobFile()
  87. {
  88. // Read the gerber file */
  89. FILE* jobFile = wxFopen( m_filename.GetFullPath(), wxT( "rt" ) );
  90. if( jobFile == nullptr )
  91. return false;
  92. LOCALE_IO toggleIo;
  93. FILE_LINE_READER jobfileReader( jobFile, m_filename.GetFullPath() ); // Will close jobFile
  94. wxString msg;
  95. wxString data;
  96. // detect the file format: old (deprecated) gerber format of official JSON format
  97. bool json_format = false;
  98. char* line = jobfileReader.ReadLine();
  99. if( !line ) // end of file
  100. return false;
  101. data = line;
  102. if( data.Contains( "{" ) )
  103. json_format = true;
  104. if( json_format )
  105. {
  106. while( ( line = jobfileReader.ReadLine() ) )
  107. data << '\n' << line;
  108. std::string err;
  109. json11::Json json_parser = json11::Json::parse( TO_UTF8( data ), err );
  110. if( !err.empty() )
  111. return false;
  112. for( auto& entry : json_parser["FilesAttributes"].array_items() )
  113. {
  114. //wxLogMessage( entry.dump().c_str() );
  115. std::string name = entry["Path"].string_value();
  116. //wxLogMessage( name.c_str() );
  117. m_GerberFiles.Add( FormatStringFromGerber( name ) );
  118. }
  119. }
  120. else
  121. {
  122. if( m_reporter )
  123. m_reporter->ReportTail( _( "This job file uses an outdated format. Please, recreate it" ),
  124. REPORTER::RPT_WARNING );
  125. return false;
  126. }
  127. return true;
  128. }
  129. bool GERBVIEW_FRAME::LoadGerberJobFile( const wxString& aFullFileName )
  130. {
  131. wxFileName filename = aFullFileName;
  132. wxString currentPath;
  133. bool success = true;
  134. if( !filename.IsOk() )
  135. {
  136. // Use the current working directory if the file name path does not exist.
  137. if( filename.DirExists() )
  138. currentPath = filename.GetPath();
  139. else
  140. currentPath = m_mruPath;
  141. wxFileDialog dlg( this, _( "Open Gerber Job File" ),
  142. currentPath,
  143. filename.GetFullName(),
  144. GerberJobFileWildcard(),
  145. wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_CHANGE_DIR );
  146. if( dlg.ShowModal() == wxID_CANCEL )
  147. return false;
  148. filename = dlg.GetPath();
  149. currentPath = filename.GetPath();
  150. m_mruPath = currentPath;
  151. }
  152. else
  153. {
  154. currentPath = filename.GetPath();
  155. m_mruPath = currentPath;
  156. }
  157. wxString msg;
  158. WX_STRING_REPORTER reporter( &msg );
  159. if( filename.IsOk() )
  160. {
  161. GERBER_JOBFILE_READER gbjReader( filename.GetFullPath(), &reporter );
  162. if( gbjReader.ReadGerberJobFile() )
  163. {
  164. // Update the list of recent drill files.
  165. UpdateFileHistory( filename.GetFullPath(), &m_jobFileHistory );
  166. Clear_DrawLayers( false );
  167. ClearMsgPanel();
  168. wxArrayString& gbrfiles = gbjReader.GetGerberFiles();
  169. success = loadListOfGerberFiles( currentPath, gbrfiles );
  170. }
  171. }
  172. SortLayersByX2Attributes();
  173. SetActiveLayer( 0 );
  174. if( !msg.IsEmpty() )
  175. {
  176. wxSafeYield(); // Allows slice of time to redraw the screen
  177. // to refresh widgets, before displaying messages
  178. HTML_MESSAGE_BOX mbox( this, _( "Messages" ) );
  179. mbox.ListSet( msg );
  180. mbox.ShowModal();
  181. }
  182. return success;
  183. }