//************************************************************************************************** // FileTasks.cpp * // --------------- * // Started : 2005-05-28 * // Last Update : 2016-11-07 * // Copyright : (C) 2005-2016 MSWaters * //************************************************************************************************** //************************************************************************************************** // * // This program is free software; you can redistribute it and/or modify it under the * // terms of the GNU General Public License as published by the Free Software Foundation; * // either version 3 of the License, or (at your option) any later version. * // * //************************************************************************************************** #include "FileTasks.hpp" #include "FrmMain.hpp" //************************************************************************************************** // Constructor. // // Argument List : // poFrmMain - A pointer to the parent frame FileTasks::FileTasks( FrmMain * poFrmMain ) : m_oPrc_gnetlist( ) { // Set the pointer to the parent frame m_poFrmMain = poFrmMain; } //************************************************************************************************** // Destructor. FileTasks::~FileTasks( ) { } //************************************************************************************************** // Execute the schematic import process. // // Return Values : // true - Success // false - Failure bool FileTasks::bExecImport( void ) { bool bRtn; TextCtrl * poTxtCtl; // Display the console page m_poFrmMain->m_oNbkTxtCtls.bSetPage( NbkTxtCtls::ePAGE_CONSOLE ); // Convert the schematic file/s to a netlist file bRtn = m_oPrc_gnetlist.bExec( ); // Print the results poTxtCtl = m_poFrmMain->m_oNbkTxtCtls.poGetPage( ); m_oPrc_gnetlist.Print( *poTxtCtl ); // Check for errors in the gnetlist output if( poTxtCtl->GetValue( ).Contains( wxT("ERROR") ) ) bRtn = false; if( poTxtCtl->GetValue( ).Contains( wxT("Backtrace") ) ) bRtn = false; // Delete the process log file m_oPrc_gnetlist.bDelLogFile( ); return( bRtn ); } //************************************************************************************************** // Initialize the Guile procedure name to be used by gnetlist when importing schematic files. void FileTasks::InitGuileProc( void ) { // Get the Guile procedure name const wxString & ros1 = g_oConfig.rosGetGuileProc( ); if( ros1.IsEmpty( ) ) return; // Set the Guile procedure name bSetGuileProc( ros1 ); } //************************************************************************************************** // Initialize the schematic file name/s. void FileTasks::InitSchemFiles( void ) { // Get the schematic file name/s const wxArrayString & roas1 = g_oConfig.roasGetSchemFiles( ); if( roas1.IsEmpty( ) ) return; // Set the schematic file name/s if( ! bSetSchemFiles( roas1 ) ) return; // Return if a netlist file has also been specified const wxString & ros1 = g_oConfig.rosGetNetLstFile( ); if( ! ros1.IsEmpty( ) ) return; // Import the schematic file/s bImport( ); } //************************************************************************************************** // Initialize the netlist file name. void FileTasks::InitNetLstFile( void ) { // Return if a netlist file has already been loaded if( ! m_poFrmMain->m_oNetLst.bIsEmpty( ) ) return; // Get the netlist file name const wxString & ros1 = g_oConfig.rosGetNetLstFile( ); if( ros1.IsEmpty( ) ) return; // Set the netlist file name if( ! bSetNetLstFile( ros1 ) ) return; // Open the netlist file bOpen( ); // Does the netlist file contain simulator specific information? if( m_poFrmMain->m_oSimnNgSp.m_oCmdPR.bIsValid( ) ) { g_oConfig.bSetSimEng( eSIMR_NGSPICE ); g_oConfig.bFlush( ); m_poFrmMain->m_oSimnGCap = m_poFrmMain->m_oSimnNgSp; } else if( m_poFrmMain->m_oSimnGCap.m_oCmdPR.bIsValid( ) ) { g_oConfig.bSetSimEng( eSIMR_GNUCAP ); g_oConfig.bFlush( ); m_poFrmMain->m_oSimnNgSp = m_poFrmMain->m_oSimnGCap; } } //************************************************************************************************** // Display a error message dialog when schematic file/s can't be imported. void FileTasks::DlgErrSchems( void ) { wxString os1, os2, os3; size_t sz1; for( sz1=0; sz1 1 ) os3 = wxT("s were"); else os3 = wxT(" was"); os1 << wxT("The schematic file") << os3 << wxT("n't converted to a netlist correctly :\n") << wxT("\n") << os2 << wxT("\n") << wxT("This is usually because gnetlist encountered problem/s\n") << wxT("while attempting to convert the schematic file/s to a netlist. \n") << wxT("Try examining the Console output to determine where the\n") << wxT("problem/s occurred.\n"); m_poFrmMain->DlgErrMsg( wxT("Import Schematic/s Error"), os1 ); } //************************************************************************************************** // Display a error message dialog when a netlist file can't be loaded. void FileTasks::DlgErrNetLst( void ) { wxString os1; os1 << wxT("The netlist file wasn't loaded correctly :\n") << wxT("\n") << wxT(" ") << m_oPrc_gnetlist.roGetNetLstFile( ).GetFullPath( ) << wxT("\n") << wxT("\n") << wxT("This is often because the file is in-complete, empty or \n") << wxT("doesn't exist.\n"); m_poFrmMain->DlgErrMsg( wxT("Netlist File Error"), os1 ); } //************************************************************************************************** // Do initialization tasks. void FileTasks::Initialize( void ) { InitGuileProc ( ); InitSchemFiles( ); InitNetLstFile( ); } //************************************************************************************************** // Check that the gnetlist binary can be found, if not display an error message. // // Return Values : // true - Success // false - Failure bool FileTasks::bIsOk_gnetlist( void ) { wxString os1; // Check that gnetlist exists and is accessible if( ! m_oPrc_gnetlist.bBinExists( ) ) { if( m_poFrmMain != NULL ) { os1 << wxT("Can't find the binary \"") << m_oPrc_gnetlist.roGetBinFile( ).GetFullName( ) << wxT("\" which is required\n") << wxT("to import schematic file/s. The path is unknown \n") << wxT("or gnetlist hasn't been installed.\n"); m_poFrmMain->DlgErrMsg( wxT("gnetlist Error"), os1 ); } return( false ); } return( true ); } //************************************************************************************************** // Set the application main frame title. // // Return Values : // true - Success // false - Failure bool FileTasks::bSetTitle( void ) { wxFileName ofn1; wxString os1; if( m_poFrmMain == NULL ) return( false ); // Create the title line os1 << wxT(" ") << "gSpiceUI vSACAMOS"; //APP_NAME if( ! rosGetNetLstFile( ).IsEmpty( ) ) { ofn1 = rosGetNetLstFile( ); if( ! ofn1.IsAbsolute( ) ) ofn1.MakeAbsolute( ); if( ofn1.GetFullPath( ).StartsWith( ofn1.GetHomeDir( ) ) ) ofn1.MakeRelativeTo( ofn1.GetHomeDir( ) ); os1 << wxT(" - "); if( ! ofn1.IsAbsolute( ) ) os1 << wxT("~/"); os1 << ofn1.GetFullPath( ); } // Set the main frames title line m_poFrmMain->wxFrame::SetTitle( os1 ); return( true ); } //************************************************************************************************** // Set a Guile procedure name to be used for importing schematic files using gNetList. // // Argument List : // rosProcName - The Guile procedure name // (Refer to gNetList documentation for list of procedure names) bool FileTasks::bSetGuileProc( const wxString & rosProcName ) { if( ! m_oPrc_gnetlist.bSetGuileProc( rosProcName ) ) return( false ); // Record the Guile procedure name currently selected g_oConfig.bSetGuileProc( rosGetGuileProc( ) ); // Write any changes to the configuration file g_oConfig.bFlush( ); return( true ); } //************************************************************************************************** // Set the schematic file name/s. // // Argument List : // roasFileNames - A string containing the full path and file name/s // // Return Values : // true - Success // false - Failure bool FileTasks::bSetSchemFiles( const wxString & rosFileNames ) { wxStringTokenizer ostk1; wxArrayString osa1; ostk1.SetString( rosFileNames ); while( ostk1.HasMoreTokens( ) ) osa1.Add( ostk1.GetNextToken( ) ); return( bSetSchemFiles( osa1 ) ); } //************************************************************************************************** // Set the schematic file name/s. // // Argument List : // roasFileNames - A string array containing the full path and file name/s // // Return Values : // true - Success // false - Failure bool FileTasks::bSetSchemFiles( const wxArrayString & roasFileNames ) { wxArrayString oas1; wxString os1; size_t sz1; if( roasFileNames.IsEmpty( ) ) { // Clear the schematic file name/s in the configuration object oas1.Empty( ); g_oConfig.bSetSchemFiles( oas1 ); g_oConfig.bFlush( ); } // Attempt to set the schematic file name/s in the gnetlist process object if( ! m_oPrc_gnetlist.bSetSchemFiles( roasFileNames ) ) return( false ); // Set the schematic file name/s if( m_poFrmMain != NULL ) m_poFrmMain->m_oNetLst.bSetSchemFiles( roasFileNames ); // Record the schematic file name/s in the configuration object g_oConfig.bSetSchemFiles( rosaGetSchemFiles( ) ); g_oConfig.bFlush( ); return( true ); } //************************************************************************************************** // Set the netlist file name. // // Argument List : // rosFileName - A string containing the full path and file name // // Return Values : // true - Success // false - Failure bool FileTasks::bSetNetLstFile( const wxString & rosFileName ) { wxString os1; if( rosFileName.IsEmpty( ) ) { // Clear the netlist file name in the configuration object g_oConfig.bSetNetLstFile( wxEmptyString ); g_oConfig.bFlush( ); } // Attempt to set the netlist file name in the gNetList process object if( ! m_oPrc_gnetlist.bSetNetLstFile( rosFileName ) ) return( false ); // Configure stuff in the main frame if( m_poFrmMain != NULL ) { m_poFrmMain->m_oNetLst.bSetLoadFile( rosFileName ); // Set load file path m_poFrmMain->m_oNetLst.bSetSaveFile( rosFileName ); // Set save file path } // Record the netlist file name in the configuration object os1 = rosGetNetLstFile( ); g_oConfig.bSetNetLstFile( os1 ); g_oConfig.bFlush( ); return( true ); } //************************************************************************************************** // Get the currently selected Guile procedure. // // Return Values : // The currently selected Guile procedure const wxString & FileTasks::rosGetGuileProc( void ) { return( m_oPrc_gnetlist.rosGetGuileProc( ) ); } //************************************************************************************************** // Get an array containing the schematic file name/s. // // Return Values : // An array of schematic file names const wxArrayString & FileTasks::rosaGetSchemFiles( void ) { static wxArrayString osa1; wxString os1; size_t szt1; osa1.Clear( ); for( szt1=0; szt1SetMessage( wxT("Open a Circuit Description File") ); poDlgOpen->SetWildcard( os1 ); poDlgOpen->SetFilterIndex( 1 ); poDlgOpen->SetDirectory( os2 ); // Display file open dialog if( poDlgOpen->ShowModal( ) != wxID_OK ) return( false ); // Delete temporary files bDelTmpFiles( ); // Set the netlist file name os1 = poDlgOpen->GetPath( ); if( ! bSetNetLstFile( os1 ) ) return( false ); // Set the path last accessed in the global configuration object g_oConfig.bSetDirLastAcc( poDlgOpen->GetDirectory( ) ); // Write any changes to the configuration file g_oConfig.bFlush( ); return( true ); } //************************************************************************************************** // Display an import file/s dialog and set the schematic file name/s. // // Return Values : // true - Success // false - Failure bool FileTasks::bDlgImport( void ) { wxFileDialog * poDlgImport; wxArrayString oas1; wxString os1, os2; long li1; // Can't display dialogue unless the application main frame has been created if( m_poFrmMain == NULL ) return( false ); // Create the different file filters os1 << wxT("gSchem files (*.sch)|*.sch|") << wxT("Protel II files (*.\?\?\?)|*.\?\?\?"); // Get the file path from the global configuration object os2 = g_oConfig.rosGetDirLastAcc( ); // Set the style bit pattern #if wxCHECK_VERSION( 2,8,0 ) li1 = wxFD_OPEN | wxFD_CHANGE_DIR | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST; #else li1 = wxOPEN | wxCHANGE_DIR | wxMULTIPLE | wxFILE_MUST_EXIST; #endif // Create and configure the file import dialog poDlgImport = new wxFileDialog( m_poFrmMain, wxT(""), wxT(""), wxT(""), wxT(""), li1 ); poDlgImport->SetMessage( wxT("Import a Schematic File/s") ); poDlgImport->SetWildcard( os1 ); poDlgImport->SetFilterIndex( 0 ); poDlgImport->SetDirectory( os2 ); // Display file import dialog if( poDlgImport->ShowModal( ) != wxID_OK ) return( false ); // Delete temporary files bDelTmpFiles( ); // Set the schematic file name/s poDlgImport->GetPaths( oas1 ); if( ! bSetSchemFiles( oas1 ) ) return( false ); // Set the netlist file name (derive it from the schematic file name) bSetNetLstFile( ); // Set the path last accessed in the global configuration object g_oConfig.bSetDirLastAcc( poDlgImport->GetDirectory( ) ); // Write any changes to the configuration file g_oConfig.bFlush( ); return( true ); } //************************************************************************************************** // Delete temporary files which may have been generated by this application. // // Eg. given the circuit description file "test-cct.sch" delete files of the form : // test-cct.ckt // test-cct.sch~ // gspiceui.log // test-cct.ngspice.dc, test-cct.ngspice.ac, ... etc. // test-cct.gnucap.op, test-cct.gnucap.dc, ... etc. bool FileTasks::bDelTmpFiles( void ) { eTypeTmpFileMgt eTmpFileMgt; wxArrayString osaDelFiles; // A list of files to delete bool bDelNetLst=false; // Is the netlist file being deleted? wxFileName ofn1; wxString os1, os2; int i1; // Check the current temporay file management strategy and return if nothing needs to be done eTmpFileMgt = g_oConfig.eGetTmpFileMgt( ); if( eTmpFileMgt == eTFM_KEEP ) return( true ); // Before looking for files to delete, get the path to the files const wxArrayString & roasSchems = rosaGetSchemFiles( ); os1 = rosGetNetLstFile( ); if( ! os1.IsEmpty( ) ) ofn1.Assign( os1 ); else if( roasSchems.GetCount( ) > 0 ) ofn1.Assign( roasSchems[ 0 ] ); if( !ofn1.IsOk( ) || !ofn1.Exists( ) ) return( false ); // If there is a schematic file add the netlist file and the schematic backup file/s to the list // of files to be deleted if( roasSchems.GetCount( ) > 0 ) { if( ! g_oConfig.bGetKeepNetLst( ) ) { osaDelFiles.Add( ofn1.GetFullPath( ) ); // Add the netlist file to the delete list bDelNetLst = true; } for( i1=0; i1 0 ) { if( m_poFrmMain!=NULL && m_poFrmMain->IsShown( ) ) { // Prompt the user if( eTmpFileMgt == eTFM_PROMPT ) { os1 = wxT("Delete Temporary Files"); os2 = wxT("\nDelete the following temporary files :\n\n"); for( i1=0; i1<(int)osaDelFiles.GetCount( ); i1++ ) os2 << wxT(" ") << osaDelFiles[ i1 ] << wxT(" \n"); i1 = wxMessageBox( os2, os1, wxYES_NO|wxICON_QUESTION, m_poFrmMain ); } else i1 = wxYES; // Delete the temporary files if( i1 == wxYES ) { for( i1=0; i1<(int)osaDelFiles.GetCount( ); i1++ ) wxRemoveFile( osaDelFiles[ i1 ] ); if( bDelNetLst ) { g_oConfig.bSetNetLstFile( wxEmptyString ); g_oConfig.bFlush( ); } } } } return( true ); } //************************************************************************************************** // Open and load a circuit description (netlist) file into the simulation objects of m_poFrmMain. // // Return Values : // true - Success // false - Failure bool FileTasks::bOpen( void ) { bool bRtn=true; // Attempt to load the circuit description file NetList::bLoadFile( ); // Load circuit description (& simulation) information into the attributes of the class hierarchy if( m_poFrmMain->m_oSimnNgSp.bLoad( ) ) m_poFrmMain->m_oSimnGCap = m_poFrmMain->m_oSimnNgSp; else if( m_poFrmMain->m_oSimnGCap.bLoad( ) ) m_poFrmMain->m_oSimnNgSp = m_poFrmMain->m_oSimnGCap; // Check for problems if( ! m_poFrmMain->m_oNetLst.bIsValid( ) ) { DlgErrNetLst( ); m_poFrmMain->m_oNbkTxtCtls.bSetPage( NbkTxtCtls::ePAGE_NETLIST ); bRtn = false; } else m_poFrmMain->SetStatusText( wxT(" Netlist file opened successfully"), FrmMain::ePANE_MESAGE ); // Set the schematic file name/s if supplied const wxArrayString & roas1 = m_poFrmMain->m_oNetLst.roasGetSchemFiles( ); if( ! roas1.IsEmpty( ) ) bSetSchemFiles( roas1 ); // Set the main frame title bSetTitle( ); return( bRtn ); } //************************************************************************************************** // Import a schematic file by converting it to a netlist using gnetlist and then loading it into the // FrmMain simulation object. // // Return Values : // true - Success // false - Failure bool FileTasks::bImport( void ) { bool bRtn=true; // Check that gnetlist binary exists and is accessible if( ! bIsOk_gnetlist( ) ) return( false ); // Convert the schematic file/s to a netlist file and load it if( bExecImport( ) ) { bSetNetLstFile( m_oPrc_gnetlist.roGetNetLstFile( ).GetFullPath( ) ); // Attempt to load the circuit description file NetList::bLoadFile( ); // Load circuit description (& simulation) info. into the attributes of the class hierarchy m_poFrmMain->m_oSimnNgSp.bLoad( ); m_poFrmMain->m_oSimnGCap.bLoad( ); if( m_poFrmMain->m_oNetLst.bIsValid( ) ) m_poFrmMain->SetStatusText( wxT(" Schematic file/s imported successfully"), FrmMain::ePANE_MESAGE ); else { DlgErrNetLst( ); m_poFrmMain->m_oNbkTxtCtls.bSetPage( NbkTxtCtls::ePAGE_NETLIST ); bRtn = false; } } else { DlgErrSchems( ); m_poFrmMain->m_oNbkTxtCtls.bSetPage( NbkTxtCtls::ePAGE_CONSOLE ); m_poFrmMain->m_oNbkTxtCtls.bSetPosn( -1 ); bRtn = false; } // Set the main frame title bSetTitle( ); return( bRtn ); } //************************************************************************************************** // Reload a simulation object whether it be from a schematic or netlist file. // // Return Values : // true - Success // false - Failure bool FileTasks::bReload( void ) { bool bRtn; // Re-initialize the text control notebook m_poFrmMain->m_oNbkTxtCtls.bInitialize( ); // Attempt to perform the reload operation if( ! m_oPrc_gnetlist.roaGetSchemFiles( ).IsEmpty( ) ) { // Reload schematic file/s bRtn = bImport( ); if( bRtn ) m_poFrmMain->SetStatusText( wxT(" Schematic file/s re-imported successfully"), FrmMain::ePANE_MESAGE ); } else if( m_oPrc_gnetlist.roGetNetLstFile( ).IsOk( ) ) { // Reload a netlist file bRtn = bOpen( ); if( bRtn ) m_poFrmMain->SetStatusText( wxT(" Netlist file reloaded successfully"), FrmMain::ePANE_MESAGE ); } else { // There's no open schematic or netlist to reload, display an error message m_poFrmMain->DlgErrMsg( wxT("Reload Operation Error"), wxT("No file is currently open.") ); bRtn = false; } return( bRtn ); } //************************************************************************************************** // Close the circuit description file. // // Return Values : // true - Success // false - Failure bool FileTasks::bClose( void ) { // Is there a file currently open? if( m_oPrc_gnetlist.roaGetSchemFiles( ).IsEmpty() && ! m_oPrc_gnetlist.roGetNetLstFile( ).IsOk() ) { // There's no open schematic or netlist to close, display an error message m_poFrmMain->DlgErrMsg( wxT("Close Operation Error"), wxT("No file is currently open.") ); return( false ); } // Delete temporary files bDelTmpFiles( ); // Clear file names m_oPrc_gnetlist.bClear( ); bSetNetLstFile( wxT("") ); bSetSchemFiles( wxT("") ); // Set the status bar message m_poFrmMain->SetStatusText( wxT(" Netlist file closed successfully"), FrmMain::ePANE_MESAGE ); // Set the text control notebook page m_poFrmMain->m_oNbkTxtCtls.bSetPage( NbkTxtCtls::ePAGE_CONSOLE ); return( true ); } //************************************************************************************************** // Do the necessary tasks before the application exits. // // Return Values : // true - Success // false - Failure bool FileTasks::bExit( void ) { // Delete temporary file/s if( ! bDelTmpFiles( ) ) return( false ); return( true ); } //**************************************************************************************************