2024-05-16 09:15:40 -07:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
2025-01-01 13:30:11 -08:00
|
|
|
* Copyright The KiCad Developers, see AUTHORS.TXT for contributors.
|
2024-05-16 09:15:40 -07:00
|
|
|
*
|
|
|
|
* 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, you may find one here:
|
|
|
|
* http://www.gnu.org/licenses/gpl-3.0.html
|
|
|
|
* or you may search the http://www.gnu.org website for the version 3 license,
|
|
|
|
* or you may write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
2025-08-04 18:59:42 +01:00
|
|
|
#include <eda_item.h>
|
|
|
|
#include <confirm.h>
|
2024-05-16 09:15:40 -07:00
|
|
|
#include <bitmaps.h>
|
|
|
|
#include <dialogs/panel_embedded_files.h>
|
|
|
|
#include <embedded_files.h>
|
2025-01-16 18:05:29 -08:00
|
|
|
#include <font/outline_font.h>
|
2024-05-16 09:15:40 -07:00
|
|
|
#include <kidialog.h>
|
|
|
|
#include <widgets/std_bitmap_button.h>
|
|
|
|
#include <widgets/wx_grid.h>
|
|
|
|
|
|
|
|
#include <wx/clipbrd.h>
|
|
|
|
#include <wx/dirdlg.h>
|
|
|
|
#include <wx/filedlg.h>
|
|
|
|
#include <wx/filename.h>
|
2025-01-16 18:05:29 -08:00
|
|
|
#include <wx/log.h>
|
2024-05-16 09:15:40 -07:00
|
|
|
#include <wx/menu.h>
|
2025-02-23 15:37:30 -08:00
|
|
|
#include <wx/wfstream.h>
|
2025-07-11 13:06:09 +01:00
|
|
|
#include <wx/wupdlock.h>
|
2024-05-16 09:15:40 -07:00
|
|
|
|
2024-12-26 18:23:18 +00:00
|
|
|
/* ---------- GRID_TRICKS for embedded files grid ---------- */
|
|
|
|
|
|
|
|
EMBEDDED_FILES_GRID_TRICKS::EMBEDDED_FILES_GRID_TRICKS( WX_GRID* aGrid ) :
|
2025-06-19 14:11:04 +01:00
|
|
|
GRID_TRICKS( aGrid ),
|
|
|
|
m_curRow( -1 )
|
2024-12-26 18:23:18 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void EMBEDDED_FILES_GRID_TRICKS::showPopupMenu( wxMenu& menu, wxGridEvent& aEvent )
|
|
|
|
{
|
|
|
|
if( const int row = aEvent.GetRow(); row >= 0 && row < m_grid->GetNumberRows() )
|
|
|
|
{
|
|
|
|
m_curRow = row;
|
|
|
|
menu.Append( EMBEDDED_FILES_GRID_TRICKS_COPY_FILENAME, _( "Copy Embedded Reference" ),
|
|
|
|
_( "Copy the reference for this embedded file" ) );
|
|
|
|
menu.AppendSeparator();
|
|
|
|
GRID_TRICKS::showPopupMenu( menu, aEvent );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_curRow = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void EMBEDDED_FILES_GRID_TRICKS::doPopupSelection( wxCommandEvent& event )
|
2024-05-16 09:15:40 -07:00
|
|
|
{
|
2024-12-26 18:23:18 +00:00
|
|
|
if( event.GetId() == EMBEDDED_FILES_GRID_TRICKS_COPY_FILENAME )
|
|
|
|
{
|
|
|
|
if( m_curRow >= 0 )
|
|
|
|
{
|
|
|
|
const wxString cellValue = m_grid->GetCellValue( m_curRow, 1 );
|
2024-05-16 09:15:40 -07:00
|
|
|
|
2024-12-26 18:23:18 +00:00
|
|
|
if( wxTheClipboard->Open() )
|
|
|
|
{
|
|
|
|
wxTheClipboard->SetData( new wxTextDataObject( cellValue ) );
|
|
|
|
wxTheClipboard->Close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GRID_TRICKS::doPopupSelection( event );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ---------- End of GRID_TRICKS for embedded files grid ---------- */
|
|
|
|
|
|
|
|
|
|
|
|
PANEL_EMBEDDED_FILES::PANEL_EMBEDDED_FILES( wxWindow* parent, EMBEDDED_FILES* aFiles ) :
|
2025-06-19 14:11:04 +01:00
|
|
|
PANEL_EMBEDDED_FILES_BASE( parent ),
|
|
|
|
m_files( aFiles ),
|
|
|
|
m_localFiles( new EMBEDDED_FILES() )
|
2024-12-26 18:23:18 +00:00
|
|
|
{
|
2024-05-16 09:15:40 -07:00
|
|
|
for( auto& [name, file] : m_files->EmbeddedFileMap() )
|
|
|
|
{
|
|
|
|
EMBEDDED_FILES::EMBEDDED_FILE* newFile = new EMBEDDED_FILES::EMBEDDED_FILE( *file );
|
|
|
|
m_localFiles->AddFile( newFile );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set up the standard buttons
|
|
|
|
m_delete_button->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
|
|
|
|
m_browse_button->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
|
|
|
|
m_files_grid->SetMargins( 0 - wxSYS_VSCROLL_X, 0 );
|
|
|
|
m_files_grid->EnableAlternateRowColors();
|
2024-12-26 18:23:18 +00:00
|
|
|
|
|
|
|
m_files_grid->PushEventHandler( new EMBEDDED_FILES_GRID_TRICKS( m_files_grid ) );
|
2025-01-26 16:51:47 -08:00
|
|
|
|
2025-06-19 14:11:04 +01:00
|
|
|
m_localFiles->SetFileAddedCallback(
|
|
|
|
[this](EMBEDDED_FILES::EMBEDDED_FILE* file)
|
2025-01-26 16:51:47 -08:00
|
|
|
{
|
2025-06-19 14:11:04 +01:00
|
|
|
for( int ii = 0; ii < m_files_grid->GetNumberRows(); ii++ )
|
|
|
|
{
|
|
|
|
if( m_files_grid->GetCellValue( ii, 1 ) == file->GetLink() )
|
|
|
|
{
|
|
|
|
m_files_grid->DeleteRows( ii );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2025-01-26 16:51:47 -08:00
|
|
|
|
2025-06-19 14:11:04 +01:00
|
|
|
m_files_grid->AppendRows( 1 );
|
|
|
|
int ii = m_files_grid->GetNumberRows() - 1;
|
|
|
|
m_files_grid->SetCellValue( ii, 0, file->name );
|
|
|
|
m_files_grid->SetCellValue( ii, 1, file->GetLink() );
|
2025-01-26 16:51:47 -08:00
|
|
|
|
2025-06-19 14:11:04 +01:00
|
|
|
} );
|
2024-12-26 18:23:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PANEL_EMBEDDED_FILES::~PANEL_EMBEDDED_FILES()
|
|
|
|
{
|
|
|
|
// Remove the GRID_TRICKS handler
|
|
|
|
m_files_grid->PopEventHandler( true );
|
2024-05-16 09:15:40 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PANEL_EMBEDDED_FILES::onSize( wxSizeEvent& event )
|
|
|
|
{
|
|
|
|
resizeGrid();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PANEL_EMBEDDED_FILES::resizeGrid()
|
|
|
|
{
|
|
|
|
int panel_width = GetClientRect().GetWidth();
|
|
|
|
int first_width = m_files_grid->GetColSize( 0 );
|
|
|
|
int second_width = m_files_grid->GetColSize( 1 );
|
|
|
|
|
|
|
|
double ratio;
|
|
|
|
|
|
|
|
if( first_width + second_width > 0 )
|
|
|
|
ratio = (double)first_width / (double)( first_width + second_width );
|
|
|
|
else
|
|
|
|
ratio = 0.3;
|
|
|
|
|
|
|
|
|
|
|
|
m_files_grid->SetColSize( 0, panel_width * ratio );
|
|
|
|
m_files_grid->SetColSize( 1, panel_width * ( 1 - ratio ) );
|
|
|
|
Layout();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool PANEL_EMBEDDED_FILES::TransferDataToWindow()
|
|
|
|
{
|
|
|
|
m_files_grid->ClearGrid();
|
2025-09-08 13:33:35 +01:00
|
|
|
m_files_grid->ClearRows();
|
2024-05-16 09:15:40 -07:00
|
|
|
|
|
|
|
int ii = 0;
|
2025-06-19 14:11:04 +01:00
|
|
|
|
2024-05-16 09:15:40 -07:00
|
|
|
for( auto& [name, file] : m_localFiles->EmbeddedFileMap() )
|
|
|
|
{
|
|
|
|
while( m_files_grid->GetNumberRows() < ii + 1 )
|
|
|
|
m_files_grid->AppendRows( 1 );
|
|
|
|
|
|
|
|
m_files_grid->SetCellValue( ii, 0, name );
|
|
|
|
m_files_grid->SetCellValue( ii, 1, file->GetLink() );
|
|
|
|
|
|
|
|
ii++;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_cbEmbedFonts->SetValue( m_files->GetAreFontsEmbedded() );
|
|
|
|
|
|
|
|
resizeGrid();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool PANEL_EMBEDDED_FILES::TransferDataFromWindow()
|
|
|
|
{
|
2025-08-04 18:59:42 +01:00
|
|
|
std::optional<bool> deleteReferences;
|
|
|
|
|
|
|
|
auto confirmDelete =
|
|
|
|
[&]() -> bool
|
|
|
|
{
|
|
|
|
if( EDA_ITEM* parent = dynamic_cast<EDA_ITEM*>( m_files ) )
|
|
|
|
{
|
|
|
|
if( parent->Type() == PCB_T )
|
|
|
|
{
|
|
|
|
return IsOK( m_parent, _( "Deleted embedded files are also referenced in some footprints.\n"
|
|
|
|
"Delete from footprints as well?" ) );
|
|
|
|
}
|
|
|
|
else if( parent->Type() == SCHEMATIC_T )
|
|
|
|
{
|
|
|
|
return IsOK( m_parent, _( "Deleted embedded files are also referenced in some symbols.\n"
|
|
|
|
"Delete from symbols as well?" ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
wxFAIL_MSG( wxT( "Unexpected embedded files owner" ) );
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
for( const auto& [name, file] : m_files->EmbeddedFileMap() )
|
|
|
|
{
|
|
|
|
if( !m_localFiles->HasFile( name ) )
|
|
|
|
{
|
|
|
|
m_files->RunOnNestedEmbeddedFiles(
|
|
|
|
[&]( EMBEDDED_FILES* nested_files )
|
|
|
|
{
|
|
|
|
if( nested_files->HasFile( name ) )
|
|
|
|
{
|
|
|
|
if( !deleteReferences.has_value() )
|
|
|
|
deleteReferences = confirmDelete();
|
|
|
|
|
|
|
|
if( deleteReferences.value() )
|
|
|
|
nested_files->RemoveFile( name, true );
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( deleteReferences.has_value() && deleteReferences.value() == false )
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2024-05-16 09:15:40 -07:00
|
|
|
m_files->ClearEmbeddedFiles();
|
|
|
|
|
|
|
|
std::vector<EMBEDDED_FILES::EMBEDDED_FILE*> files;
|
|
|
|
|
2025-06-19 14:11:04 +01:00
|
|
|
for( const auto& [name, file] : m_localFiles->EmbeddedFileMap() )
|
|
|
|
files.push_back( file );
|
2024-05-16 09:15:40 -07:00
|
|
|
|
2025-06-19 14:11:04 +01:00
|
|
|
for( EMBEDDED_FILES::EMBEDDED_FILE* file : files )
|
2024-05-16 09:15:40 -07:00
|
|
|
{
|
|
|
|
m_files->AddFile( file );
|
|
|
|
m_localFiles->RemoveFile( file->name, false );
|
|
|
|
}
|
|
|
|
|
|
|
|
m_files->SetAreFontsEmbedded( m_cbEmbedFonts->IsChecked() );
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2025-01-16 18:05:29 -08:00
|
|
|
void PANEL_EMBEDDED_FILES::onFontEmbedClick( wxCommandEvent& event )
|
|
|
|
{
|
2025-07-11 13:06:09 +01:00
|
|
|
wxWindowUpdateLocker updateLock( this );
|
2025-07-10 16:49:04 +01:00
|
|
|
|
2025-01-16 18:05:29 -08:00
|
|
|
int row_pos = m_files_grid->GetGridCursorRow();
|
|
|
|
int col_pos = m_files_grid->GetGridCursorCol();
|
|
|
|
wxString row_name;
|
|
|
|
|
|
|
|
if( row_pos >= 0 )
|
|
|
|
row_name = m_files_grid->GetCellValue( row_pos, 0 );
|
|
|
|
|
|
|
|
for( int ii = 0; ii < m_files_grid->GetNumberRows(); ii++ )
|
|
|
|
{
|
|
|
|
wxString name = m_files_grid->GetCellValue( ii, 0 );
|
|
|
|
|
|
|
|
EMBEDDED_FILES::EMBEDDED_FILE* file = m_localFiles->GetEmbeddedFile( name );
|
|
|
|
|
|
|
|
if( file && file->type == EMBEDDED_FILES::EMBEDDED_FILE::FILE_TYPE::FONT )
|
|
|
|
{
|
|
|
|
m_files_grid->DeleteRows( ii );
|
|
|
|
ii--;
|
|
|
|
m_localFiles->RemoveFile( name );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( m_cbEmbedFonts->IsChecked() )
|
|
|
|
{
|
|
|
|
std::set<KIFONT::OUTLINE_FONT*> fonts = m_files->GetFonts();
|
|
|
|
|
|
|
|
for( KIFONT::OUTLINE_FONT* font : fonts )
|
|
|
|
{
|
2025-06-19 14:11:04 +01:00
|
|
|
EMBEDDED_FILES::EMBEDDED_FILE* result = m_localFiles->AddFile( font->GetFileName(), true );
|
2025-01-16 18:05:29 -08:00
|
|
|
|
|
|
|
if( !result )
|
|
|
|
{
|
|
|
|
wxLogTrace( wxT( "KICAD_EMBED" ), wxString::Format( "Could not embed font %s",
|
|
|
|
font->GetFileName() ) );
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( row_pos >= 0 )
|
|
|
|
{
|
|
|
|
col_pos = std::max( std::min( col_pos, m_files_grid->GetNumberCols() - 1 ), 0 );
|
|
|
|
row_pos = std::max( std::min( row_pos, m_files_grid->GetNumberRows() - 1 ), 0 );
|
|
|
|
m_files_grid->SetGridCursor( row_pos, col_pos );
|
|
|
|
|
|
|
|
for( int ii = 0; ii < m_files_grid->GetNumberRows(); ++ii )
|
|
|
|
{
|
|
|
|
if( m_files_grid->GetCellValue( ii, 0 ) == row_name )
|
|
|
|
{
|
|
|
|
m_files_grid->SetGridCursor( ii, col_pos );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2025-01-26 16:51:47 -08:00
|
|
|
EMBEDDED_FILES::EMBEDDED_FILE* PANEL_EMBEDDED_FILES::AddEmbeddedFile( const wxString& aFile )
|
2024-05-16 09:15:40 -07:00
|
|
|
{
|
2025-01-26 16:51:47 -08:00
|
|
|
wxFileName fileName( aFile );
|
|
|
|
wxString name = fileName.GetFullName();
|
2024-05-16 09:15:40 -07:00
|
|
|
|
2025-01-26 16:51:47 -08:00
|
|
|
if( m_localFiles->HasFile( name ) )
|
2024-05-16 09:15:40 -07:00
|
|
|
{
|
2025-01-26 16:51:47 -08:00
|
|
|
wxString msg = wxString::Format( _( "File '%s' already exists." ), name );
|
2024-05-16 09:15:40 -07:00
|
|
|
|
2025-01-26 16:51:47 -08:00
|
|
|
KIDIALOG errorDlg( m_parent, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
|
|
|
|
errorDlg.SetOKLabel( _( "Overwrite" ) );
|
2024-05-16 09:15:40 -07:00
|
|
|
|
2025-01-26 16:51:47 -08:00
|
|
|
if( errorDlg.ShowModal() != wxID_OK )
|
|
|
|
return nullptr;
|
2024-05-16 09:15:40 -07:00
|
|
|
|
2025-01-26 16:51:47 -08:00
|
|
|
for( int ii = 0; ii < m_files_grid->GetNumberRows(); ii++ )
|
|
|
|
{
|
|
|
|
if( m_files_grid->GetCellValue( ii, 0 ) == name )
|
2024-05-16 09:15:40 -07:00
|
|
|
{
|
2025-01-26 16:51:47 -08:00
|
|
|
m_files_grid->DeleteRows( ii );
|
|
|
|
break;
|
2024-05-16 09:15:40 -07:00
|
|
|
}
|
|
|
|
}
|
2025-01-26 16:51:47 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
EMBEDDED_FILES::EMBEDDED_FILE* result = m_localFiles->AddFile( fileName, true );
|
|
|
|
|
|
|
|
if( !result )
|
|
|
|
{
|
|
|
|
wxString msg = wxString::Format( _( "Failed to add file '%s'." ), name );
|
|
|
|
|
|
|
|
KIDIALOG errorDlg( m_parent, msg, _( "Error" ), wxOK | wxICON_ERROR );
|
|
|
|
errorDlg.ShowModal();
|
|
|
|
return nullptr;
|
|
|
|
}
|
2024-05-16 09:15:40 -07:00
|
|
|
|
2025-01-26 16:51:47 -08:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2025-02-11 00:10:56 +03:00
|
|
|
void PANEL_EMBEDDED_FILES::onAddEmbeddedFiles( wxCommandEvent& event )
|
2025-01-26 16:51:47 -08:00
|
|
|
{
|
2025-02-11 00:10:56 +03:00
|
|
|
// TODO: Update strings to reflect that multiple files can be selected.
|
2025-01-26 16:51:47 -08:00
|
|
|
wxFileDialog fileDialog( this, _( "Select a file to embed" ), wxEmptyString, wxEmptyString,
|
2025-03-10 16:05:30 +03:00
|
|
|
_( "All Files" ) + wxT( " (*.*)|*.*" ),
|
2025-02-11 00:10:56 +03:00
|
|
|
wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE );
|
2025-01-26 16:51:47 -08:00
|
|
|
|
|
|
|
if( fileDialog.ShowModal() == wxID_OK )
|
2025-02-11 00:10:56 +03:00
|
|
|
{
|
|
|
|
wxArrayString paths;
|
|
|
|
fileDialog.GetPaths( paths );
|
|
|
|
|
2025-06-19 14:11:04 +01:00
|
|
|
for( const wxString& path : paths )
|
2025-02-11 00:10:56 +03:00
|
|
|
AddEmbeddedFile( path );
|
|
|
|
}
|
2025-01-26 16:51:47 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool PANEL_EMBEDDED_FILES::RemoveEmbeddedFile( const wxString& aFileName )
|
|
|
|
{
|
|
|
|
wxString name = aFileName;
|
2024-05-16 09:15:40 -07:00
|
|
|
|
2025-01-26 16:51:47 -08:00
|
|
|
if( name.StartsWith( FILEEXT::KiCadUriPrefix ) )
|
|
|
|
name = name.Mid( FILEEXT::KiCadUriPrefix.size() + 3 );
|
|
|
|
|
|
|
|
int row = std::max( 0, m_files_grid->GetGridCursorRow() );
|
|
|
|
|
|
|
|
for( int ii = 0; ii < m_files_grid->GetNumberRows(); ii++ )
|
|
|
|
{
|
|
|
|
if( m_files_grid->GetCellValue( ii, 0 ) == name )
|
2024-05-16 09:15:40 -07:00
|
|
|
{
|
2025-01-26 16:51:47 -08:00
|
|
|
m_files_grid->DeleteRows( ii );
|
|
|
|
m_localFiles->RemoveFile( name );
|
2024-05-16 09:15:40 -07:00
|
|
|
|
2025-01-26 16:51:47 -08:00
|
|
|
if( row < m_files_grid->GetNumberRows() )
|
|
|
|
m_files_grid->SetGridCursor( row, 0 );
|
|
|
|
else if( m_files_grid->GetNumberRows() > 0 )
|
|
|
|
m_files_grid->SetGridCursor( m_files_grid->GetNumberRows() - 1, 0 );
|
2024-05-16 09:15:40 -07:00
|
|
|
|
2025-01-26 16:51:47 -08:00
|
|
|
return true;
|
|
|
|
}
|
2024-05-16 09:15:40 -07:00
|
|
|
}
|
2025-01-26 16:51:47 -08:00
|
|
|
|
|
|
|
return false;
|
2024-05-16 09:15:40 -07:00
|
|
|
}
|
|
|
|
|
2025-01-26 16:51:47 -08:00
|
|
|
|
2024-05-16 09:15:40 -07:00
|
|
|
void PANEL_EMBEDDED_FILES::onDeleteEmbeddedFile( wxCommandEvent& event )
|
|
|
|
{
|
2025-07-24 17:55:00 +01:00
|
|
|
m_files_grid->OnDeleteRows(
|
|
|
|
[&]( int row )
|
|
|
|
{
|
|
|
|
wxString name = m_files_grid->GetCellValue( row, 0 );
|
2024-05-16 09:15:40 -07:00
|
|
|
|
2025-07-24 17:55:00 +01:00
|
|
|
m_localFiles->RemoveFile( name );
|
|
|
|
m_files_grid->DeleteRows( row );
|
|
|
|
} );
|
2024-05-16 09:15:40 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PANEL_EMBEDDED_FILES::onExportFiles( wxCommandEvent& event )
|
|
|
|
{
|
|
|
|
wxDirDialog dirDialog( this, _( "Select a directory to export files" ) );
|
|
|
|
|
|
|
|
if( dirDialog.ShowModal() != wxID_OK )
|
|
|
|
return;
|
|
|
|
|
|
|
|
wxString path = dirDialog.GetPath();
|
|
|
|
|
|
|
|
for( auto& [name, file] : m_localFiles->EmbeddedFileMap() )
|
|
|
|
{
|
|
|
|
wxFileName fileName( path, name );
|
|
|
|
|
|
|
|
if( fileName.FileExists() )
|
|
|
|
{
|
2025-06-19 14:11:04 +01:00
|
|
|
wxString msg = wxString::Format( _( "File '%s' already exists." ), fileName.GetFullName() );
|
2024-05-16 09:15:40 -07:00
|
|
|
|
2025-06-19 14:11:04 +01:00
|
|
|
KIDIALOG errorDlg( m_parent, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
|
2024-05-16 09:15:40 -07:00
|
|
|
errorDlg.SetOKCancelLabels( _( "Overwrite" ), _( "Skip" ) );
|
|
|
|
errorDlg.DoNotShowCheckbox( __FILE__, __LINE__ );
|
|
|
|
|
|
|
|
if( errorDlg.ShowModal() != wxID_OK )
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool skip_file = false;
|
|
|
|
|
|
|
|
while( 1 )
|
|
|
|
{
|
|
|
|
if( !fileName.IsDirWritable() )
|
|
|
|
{
|
|
|
|
#ifndef __WXMAC__
|
2025-06-19 14:11:04 +01:00
|
|
|
wxString msg = wxString::Format( _( "Directory '%s' is not writable." ), fileName.GetFullName() );
|
2024-05-16 09:15:40 -07:00
|
|
|
#else
|
2025-06-19 14:11:04 +01:00
|
|
|
wxString msg = wxString::Format( _( "Folder '%s' is not writable." ), fileName.GetPath() );
|
2024-05-16 09:15:40 -07:00
|
|
|
#endif
|
|
|
|
// Don't set a 'do not show again' checkbox for this dialog
|
|
|
|
KIDIALOG errorDlg( m_parent, msg, _( "Error" ), wxYES_NO | wxCANCEL | wxICON_ERROR );
|
|
|
|
errorDlg.SetYesNoCancelLabels( _( "Retry" ), _( "Skip" ), _( "Cancel" ) );
|
|
|
|
|
|
|
|
int result = errorDlg.ShowModal();
|
|
|
|
|
|
|
|
if( result == wxID_CANCEL )
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if( result == wxID_NO )
|
|
|
|
{
|
|
|
|
skip_file = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( skip_file )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
2025-02-23 15:37:30 -08:00
|
|
|
wxFFileOutputStream out( fileName.GetFullPath() );
|
|
|
|
|
|
|
|
if( !out.IsOk() )
|
2024-05-16 09:15:40 -07:00
|
|
|
{
|
2025-06-19 14:11:04 +01:00
|
|
|
wxString msg = wxString::Format( _( "Failed to open file '%s'." ), fileName.GetFullName() );
|
2024-05-16 09:15:40 -07:00
|
|
|
|
|
|
|
KIDIALOG errorDlg( m_parent, msg, _( "Error" ), wxOK | wxICON_ERROR );
|
|
|
|
errorDlg.ShowModal();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2025-02-23 15:37:30 -08:00
|
|
|
out.Write( file->decompressedData.data(), file->decompressedData.size() );
|
|
|
|
|
|
|
|
if( !out.IsOk() || ( out.LastWrite() != file->decompressedData.size() ) )
|
2024-05-16 09:15:40 -07:00
|
|
|
{
|
2025-06-19 14:11:04 +01:00
|
|
|
wxString msg = wxString::Format( _( "Failed to write file '%s'." ), fileName.GetFullName() );
|
2024-05-16 09:15:40 -07:00
|
|
|
|
|
|
|
KIDIALOG errorDlg( m_parent, msg, _( "Error" ), wxOK | wxICON_ERROR );
|
2025-02-23 15:37:30 -08:00
|
|
|
|
2024-05-16 09:15:40 -07:00
|
|
|
errorDlg.ShowModal();
|
|
|
|
}
|
|
|
|
}
|
2025-01-12 11:27:18 -05:00
|
|
|
}
|