diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index dcb77f1105..efee34a557 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -326,6 +326,7 @@ set( COMMON_DLG_SRCS dialogs/dialog_embed_files.cpp dialogs/dialog_global_lib_table_config.cpp dialogs/dialog_global_lib_table_config_base.cpp + dialogs/dialog_global_design_block_lib_table_config.cpp dialogs/dialog_grid_settings.cpp dialogs/dialog_grid_settings_base.cpp dialogs/dialog_hotkey_list.cpp diff --git a/common/design_block_info.h b/common/design_block_info.h index 9d8862bce4..6bf05d70fd 100644 --- a/common/design_block_info.h +++ b/common/design_block_info.h @@ -146,9 +146,6 @@ public: virtual ~DESIGN_BLOCK_LIST() {} - virtual void WriteCacheToFile( const wxString& aFilePath ){}; - virtual void ReadCacheFromFile( const wxString& aFilePath ){}; - /** * @return the number of items stored in list */ diff --git a/common/design_block_info_impl.cpp b/common/design_block_info_impl.cpp index 84eff9a1fb..dc3abbc156 100644 --- a/common/design_block_info_impl.cpp +++ b/common/design_block_info_impl.cpp @@ -294,83 +294,3 @@ DESIGN_BLOCK_LIST_IMPL::DESIGN_BLOCK_LIST_IMPL() : m_list_timestamp( 0 ), m_progress_reporter( nullptr ), m_cancelled( false ) { } - - -void DESIGN_BLOCK_LIST_IMPL::WriteCacheToFile( const wxString& aFilePath ) -{ - wxFileName tmpFileName = wxFileName::CreateTempFileName( aFilePath ); - wxFFileOutputStream outStream( tmpFileName.GetFullPath() ); - wxTextOutputStream txtStream( outStream ); - - if( !outStream.IsOk() ) - { - return; - } - - txtStream << wxString::Format( wxT( "%lld" ), m_list_timestamp ) << endl; - - for( std::unique_ptr<DESIGN_BLOCK_INFO>& dbinfo : m_list ) - { - txtStream << dbinfo->GetLibNickname() << endl; - txtStream << dbinfo->GetName() << endl; - txtStream << EscapeString( dbinfo->GetDesc(), CTX_LINE ) << endl; - txtStream << EscapeString( dbinfo->GetKeywords(), CTX_LINE ) << endl; - txtStream << wxString::Format( wxT( "%d" ), dbinfo->GetOrderNum() ) << endl; - } - - txtStream.Flush(); - outStream.Close(); - - // Preserve the permissions of the current file - KIPLATFORM::IO::DuplicatePermissions( aFilePath, tmpFileName.GetFullPath() ); - - if( !wxRenameFile( tmpFileName.GetFullPath(), aFilePath, true ) ) - { - // cleanup in case rename failed - // its also not the end of the world since this is just a cache file - wxRemoveFile( tmpFileName.GetFullPath() ); - } -} - - -void DESIGN_BLOCK_LIST_IMPL::ReadCacheFromFile( const wxString& aFilePath ) -{ - wxTextFile cacheFile( aFilePath ); - - m_list_timestamp = 0; - m_list.clear(); - - try - { - if( cacheFile.Exists() && cacheFile.Open() ) - { - cacheFile.GetFirstLine().ToLongLong( &m_list_timestamp ); - - while( cacheFile.GetCurrentLine() + 6 < cacheFile.GetLineCount() ) - { - wxString libNickname = cacheFile.GetNextLine(); - wxString name = cacheFile.GetNextLine(); - wxString desc = UnescapeString( cacheFile.GetNextLine() ); - wxString keywords = UnescapeString( cacheFile.GetNextLine() ); - int orderNum = wxAtoi( cacheFile.GetNextLine() ); - - DESIGN_BLOCK_INFO_IMPL* dbinfo = - new DESIGN_BLOCK_INFO_IMPL( libNickname, name, desc, keywords, orderNum ); - - m_list.emplace_back( std::unique_ptr<DESIGN_BLOCK_INFO>( dbinfo ) ); - } - } - } - catch( ... ) - { - // whatever went wrong, invalidate the cache - m_list_timestamp = 0; - } - - // Sanity check: an empty list is very unlikely to be correct. - if( m_list.size() == 0 ) - m_list_timestamp = 0; - - if( cacheFile.IsOpened() ) - cacheFile.Close(); -} diff --git a/common/design_block_info_impl.h b/common/design_block_info_impl.h index 0f1f6bc4ce..cd056b3bd1 100644 --- a/common/design_block_info_impl.h +++ b/common/design_block_info_impl.h @@ -83,9 +83,6 @@ public: DESIGN_BLOCK_LIST_IMPL(); virtual ~DESIGN_BLOCK_LIST_IMPL(){}; - void WriteCacheToFile( const wxString& aFilePath ) override; - void ReadCacheFromFile( const wxString& aFilePath ) override; - bool ReadDesignBlockFiles( DESIGN_BLOCK_LIB_TABLE* aTable, const wxString* aNickname = nullptr, PROGRESS_REPORTER* aProgressReporter = nullptr ) override; diff --git a/common/dialogs/dialog_global_design_block_lib_table_config.cpp b/common/dialogs/dialog_global_design_block_lib_table_config.cpp new file mode 100644 index 0000000000..ebd8c77cad --- /dev/null +++ b/common/dialogs/dialog_global_design_block_lib_table_config.cpp @@ -0,0 +1,142 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2019 Wayne Stambaugh <stambaughw@gmail.com> + * Copyright (C) 2017-2019 KiCad Developers, see AUTHORS.txt for contributors. + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "dialog_global_design_block_lib_table_config.h" + +#include <confirm.h> +#include <kiface_base.h> +#include <kiway.h> +#include <macros.h> + +#include "design_block_lib_table.h" + + +DIALOG_GLOBAL_DESIGN_BLOCK_LIB_TABLE_CONFIG::DIALOG_GLOBAL_DESIGN_BLOCK_LIB_TABLE_CONFIG( + wxWindow* aParent ) : + DIALOG_GLOBAL_LIB_TABLE_CONFIG( aParent, _( "design block" ), KIWAY::FACE_SCH ) +{ +} + + +DIALOG_GLOBAL_DESIGN_BLOCK_LIB_TABLE_CONFIG::~DIALOG_GLOBAL_DESIGN_BLOCK_LIB_TABLE_CONFIG() +{ +} + + +wxFileName DIALOG_GLOBAL_DESIGN_BLOCK_LIB_TABLE_CONFIG::GetGlobalTableFileName() +{ + return DESIGN_BLOCK_LIB_TABLE::GetGlobalTableFileName(); +} + + +bool DIALOG_GLOBAL_DESIGN_BLOCK_LIB_TABLE_CONFIG::TransferDataFromWindow() +{ + // Create an empty table if requested by the user. + if( m_emptyRb->GetValue() ) + { + DESIGN_BLOCK_LIB_TABLE emptyTable; + + try + { + emptyTable.Save( DESIGN_BLOCK_LIB_TABLE::GetGlobalTableFileName() ); + } + catch( const IO_ERROR& ioe ) + { + DisplayError( this, + wxString::Format( _( "Error creating design block library table '%s'.\n" + "%s" ), + DESIGN_BLOCK_LIB_TABLE::GetGlobalTableFileName(), + ioe.What() ) ); + return false; + } + } + else + { + wxString fileName = m_filePicker1->GetPath(); + + if( fileName.IsEmpty() ) + { + DisplayError( this, _( "Please select a design block library table file." ) ); + return false; + } + + wxFileName fn = fileName; + + // Make sure the design block library table to copy actually exists. + if( !fn.FileExists() ) + { + DisplayError( this, wxString::Format( _( "File '%s' not found." ), fn.GetFullPath() ) ); + return false; + } + + // Make sure the design block library table to copy is a valid design block library table file. + DESIGN_BLOCK_LIB_TABLE tmpTable; + + try + { + tmpTable.Load( fn.GetFullPath() ); + } + catch( const IO_ERROR& ioe ) + { + DisplayError( this, + wxString::Format( _( "Error reading design block library table '%s'.\n" + "%s" ), + fn.GetFullPath(), ioe.What() ) ); + return false; + } + + // Create the config path if it doesn't already exist. + wxFileName designBlockTableFileName = DESIGN_BLOCK_LIB_TABLE::GetGlobalTableFileName(); + + if( !designBlockTableFileName.DirExists() + && !designBlockTableFileName.Mkdir( 0x777, wxPATH_MKDIR_FULL ) ) + { + DisplayError( this, wxString::Format( _( "Cannot create global library table '%s'." ), + designBlockTableFileName.GetPath() ) ); + return false; + } + + // Copy the global design block library table file to the user config. + if( !::wxCopyFile( fn.GetFullPath(), designBlockTableFileName.GetFullPath() ) ) + { + DisplayError( + this, + wxString::Format( _( "Error copying global design block library table '%s' " + "to '%s'." ), + fn.GetFullPath(), designBlockTableFileName.GetFullPath() ) ); + return false; + } + } + + // Load the successfully copied design block library table file. This should not fail since the + // file was tested above. Check for failure anyway to keep the compiler from complaining. + try + { + if( !DESIGN_BLOCK_LIB_TABLE::LoadGlobalTable( + DESIGN_BLOCK_LIB_TABLE::GetGlobalLibTable() ) ) + return false; + } + catch( const IO_ERROR& ) + { + return false; + } + + return true; +} diff --git a/common/dialogs/dialog_global_design_block_lib_table_config.h b/common/dialogs/dialog_global_design_block_lib_table_config.h new file mode 100644 index 0000000000..1cd213a430 --- /dev/null +++ b/common/dialogs/dialog_global_design_block_lib_table_config.h @@ -0,0 +1,37 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2017-2024 KiCad Developers, see AUTHORS.txt for contributors. + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _DIALOG_GLOBAL_DESIGN_BLOCK_LIB_TABLE_CONFIG_H_ +#define _DIALOG_GLOBAL_DESIGN_BLOCK_LIB_TABLE_CONFIG_H_ + +#include <dialogs/dialog_global_lib_table_config.h> + + +class DIALOG_GLOBAL_DESIGN_BLOCK_LIB_TABLE_CONFIG : public DIALOG_GLOBAL_LIB_TABLE_CONFIG +{ +public: + DIALOG_GLOBAL_DESIGN_BLOCK_LIB_TABLE_CONFIG( wxWindow* aParent ); + virtual ~DIALOG_GLOBAL_DESIGN_BLOCK_LIB_TABLE_CONFIG(); + + bool TransferDataFromWindow() override; + + virtual wxFileName GetGlobalTableFileName() override; +}; + +#endif // _DIALOG_GLOBAL_DESIGN_BLOCK_LIB_TABLE_CONFIG_H_ diff --git a/eeschema/eeschema.cpp b/eeschema/eeschema.cpp index 3d6980963c..62342ef68d 100644 --- a/eeschema/eeschema.cpp +++ b/eeschema/eeschema.cpp @@ -33,10 +33,12 @@ #include "eeschema_helpers.h" #include <eeschema_settings.h> #include <sch_edit_frame.h> +#include <design_block_lib_table.h> #include <symbol_edit_frame.h> #include <symbol_viewer_frame.h> #include <symbol_chooser_frame.h> #include <symbol_lib_table.h> +#include <dialogs/dialog_global_design_block_lib_table_config.h> #include <dialogs/dialog_global_sym_lib_table_config.h> #include <dialogs/panel_grid_settings.h> #include <dialogs/panel_simulator_preferences.h> @@ -346,6 +348,7 @@ static struct IFACE : public KIFACE_BASE, public UNITS_PROVIDER private: bool loadGlobalLibTable(); + bool loadGlobalDesignBlockLibTable(); std::unique_ptr<EESCHEMA_JOBS_HANDLER> m_jobHandler; @@ -386,7 +389,7 @@ bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits, KIWAY* aKiway ) start_common( aCtlBits ); - if( !loadGlobalLibTable() ) + if( !loadGlobalLibTable() || !loadGlobalDesignBlockLibTable() ) { // we didnt get anywhere deregister the settings aProgram->GetSettingsManager().FlushAndRelease( symSettings, false ); @@ -456,6 +459,51 @@ bool IFACE::loadGlobalLibTable() } +bool IFACE::loadGlobalDesignBlockLibTable() +{ + wxFileName fn = DESIGN_BLOCK_LIB_TABLE::GetGlobalTableFileName(); + + if( !fn.FileExists() ) + { + if( !( m_start_flags & KFCTL_CLI ) ) + { + // Ensure the splash screen does not hide the dialog: + Pgm().HideSplash(); + + DIALOG_GLOBAL_DESIGN_BLOCK_LIB_TABLE_CONFIG dbDialog( nullptr ); + + if( dbDialog.ShowModal() != wxID_OK ) + return false; + } + } + else + { + try + { + // The global table is not related to a specific project. All projects + // will use the same global table. So the KIFACE::OnKifaceStart() contract + // of avoiding anything project specific is not violated here. + if( !DESIGN_BLOCK_LIB_TABLE::LoadGlobalTable( + DESIGN_BLOCK_LIB_TABLE::GetGlobalLibTable() ) ) + return false; + } + catch( const IO_ERROR& ioe ) + { + // if we are here, a incorrect global design block library table was found. + // Incorrect global design block library table is not a fatal error: + // the user just has to edit the (partially) loaded table. + wxString msg = _( + "An error occurred attempting to load the global design block library table.\n" + "Please edit this global design block library table in Preferences menu." ); + + DisplayErrorMessage( nullptr, msg, ioe.What() ); + } + } + + return true; +} + + void IFACE::OnKifaceEnd() { end_common(); diff --git a/kicad/kicad.cpp b/kicad/kicad.cpp index 05f5936a7b..707e31aa8b 100644 --- a/kicad/kicad.cpp +++ b/kicad/kicad.cpp @@ -62,8 +62,6 @@ #include <api/api_server.h> #endif -#include <design_block_lib_table.h> - // a dummy to quiet linking with EDA_BASE_FRAME::config(); #include <kiface_base.h> KIFACE_BASE& Kiface() @@ -355,27 +353,6 @@ bool PGM_KICAD::OnPgmInit() } } - try - { - DESIGN_BLOCK_LIB_TABLE::LoadGlobalTable( DESIGN_BLOCK_LIB_TABLE::GetGlobalLibTable() ); - } - catch( const IO_ERROR& ioe ) - { - // if we are here, a incorrect global design block library table was found. - // Incorrect global design block library table is not a fatal error: - // the user just has to edit the (partially) loaded table. - wxString msg = _( "An error occurred attempting to load the global design block library " - "table.\n" - "Please edit this global design block library table in Preferences " - "menu." ); - - DisplayErrorMessage( nullptr, msg, ioe.What() ); - } - - if( managerFrame->IsProjectActive() && DESIGN_BLOCK_LIB_TABLE::GetGlobalList().GetCount() == 0 ) - DESIGN_BLOCK_LIB_TABLE::GetGlobalList().ReadCacheFromFile( - Prj().GetProjectPath() + wxT( "design-block-info-cache" ) ); - frame->Show( true ); frame->Raise(); diff --git a/kicad/pgm_kicad.h b/kicad/pgm_kicad.h index d131e0b4c9..12e98c7451 100644 --- a/kicad/pgm_kicad.h +++ b/kicad/pgm_kicad.h @@ -28,9 +28,6 @@ #include <pgm_base.h> #include <bin_mod.h> -class DESIGN_BLOCK_LIB_TABLE; -class DESIGN_BLOCK_LIST_IMPL; - /** * PGM_KICAD * extends PGM_BASE to bring in FileHistory() and PdfBrowser() which were moved from EDA_APP