mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-13 17:53:11 +02:00
Add ability to embed files in various elements
Schematics, symbols, boards and footprints all get the ability to store files inside their file structures. File lookups now have a kicad-embed:// URI to allow various parts of KiCad to refer to files stored in this manner. kicad-embed://datasheet.pdf references the file named "datasheet.pdf" embedded in the document. Embeds are allowed in schematics, boards, symbols and footprints. Currently supported embeddings are Datasheets, 3D Models and drawingsheets Fixes https://gitlab.com/kicad/code/kicad/-/issues/6918 Fixes https://gitlab.com/kicad/code/kicad/-/issues/2376 Fixes https://gitlab.com/kicad/code/kicad/-/issues/17827
This commit is contained in:
parent
8d0c629f37
commit
77797103f7
@ -202,12 +202,12 @@ S3D_CACHE::~S3D_CACHE()
|
||||
|
||||
|
||||
SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, const wxString& aBasePath,
|
||||
S3D_CACHE_ENTRY** aCachePtr )
|
||||
S3D_CACHE_ENTRY** aCachePtr, const EMBEDDED_FILES* aEmbeddedFiles )
|
||||
{
|
||||
if( aCachePtr )
|
||||
*aCachePtr = nullptr;
|
||||
|
||||
wxString full3Dpath = m_FNResolver->ResolvePath( aModelFile, aBasePath );
|
||||
wxString full3Dpath = m_FNResolver->ResolvePath( aModelFile, aBasePath, aEmbeddedFiles );
|
||||
|
||||
if( full3Dpath.empty() )
|
||||
{
|
||||
@ -272,9 +272,9 @@ SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, const wxString& aBasePa
|
||||
}
|
||||
|
||||
|
||||
SCENEGRAPH* S3D_CACHE::Load( const wxString& aModelFile, const wxString& aBasePath )
|
||||
SCENEGRAPH* S3D_CACHE::Load( const wxString& aModelFile, const wxString& aBasePath, const EMBEDDED_FILES* aEmbeddedFiles )
|
||||
{
|
||||
return load( aModelFile, aBasePath );
|
||||
return load( aModelFile, aBasePath, nullptr, aEmbeddedFiles );
|
||||
}
|
||||
|
||||
|
||||
@ -631,10 +631,11 @@ void S3D_CACHE::ClosePlugins()
|
||||
}
|
||||
|
||||
|
||||
S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName, const wxString& aBasePath )
|
||||
S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName, const wxString& aBasePath,
|
||||
const EMBEDDED_FILES* aEmbeddedFiles )
|
||||
{
|
||||
S3D_CACHE_ENTRY* cp = nullptr;
|
||||
SCENEGRAPH* sp = load( aModelFileName, aBasePath,&cp );
|
||||
SCENEGRAPH* sp = load( aModelFileName, aBasePath, &cp, aEmbeddedFiles );
|
||||
|
||||
if( !sp )
|
||||
return nullptr;
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <project.h>
|
||||
#include <wx/string.h>
|
||||
|
||||
class EMBEDDED_FILES;
|
||||
class PGM_BASE;
|
||||
class S3D_CACHE_ENTRY;
|
||||
class SCENEGRAPH;
|
||||
@ -93,9 +94,10 @@ public:
|
||||
*
|
||||
* @param aModelFile is the partial or full path to the model to be loaded.
|
||||
* @param aBasePath is the path to search for any relative files
|
||||
* @param aEmbeddedFiles is a pointer to the embedded files list.
|
||||
* @return true if the model was successfully loaded, otherwise false.
|
||||
*/
|
||||
SCENEGRAPH* Load( const wxString& aModelFile, const wxString& aBasePath );
|
||||
SCENEGRAPH* Load( const wxString& aModelFile, const wxString& aBasePath, const EMBEDDED_FILES* aEmbeddedFiles );
|
||||
|
||||
FILENAME_RESOLVER* GetResolver() noexcept;
|
||||
|
||||
@ -123,9 +125,11 @@ public:
|
||||
* structure for display by a renderer.
|
||||
*
|
||||
* @param aModelFileName is the full path to the model to be loaded.
|
||||
* @param aBasePath is the path to search for any relative files.
|
||||
* @param aEmbeddedFiles is a pointer to the embedded files list.
|
||||
* @return is a pointer to the render data or NULL if not available.
|
||||
*/
|
||||
S3DMODEL* GetModel( const wxString& aModelFileName, const wxString& aBasePath );
|
||||
S3DMODEL* GetModel( const wxString& aModelFileName, const wxString& aBasePath, const EMBEDDED_FILES* aEmbeddedFiles );
|
||||
|
||||
/**
|
||||
* Delete up old cache files in cache directory.
|
||||
@ -165,7 +169,9 @@ private:
|
||||
bool saveCacheData( S3D_CACHE_ENTRY* aCacheItem );
|
||||
|
||||
// the real load function (can supply a cache entry pointer to member functions)
|
||||
SCENEGRAPH* load( const wxString& aModelFile, const wxString& aBasePath, S3D_CACHE_ENTRY** aCachePtr = nullptr );
|
||||
SCENEGRAPH* load( const wxString& aModelFile, const wxString& aBasePath,
|
||||
S3D_CACHE_ENTRY** aCachePtr = nullptr,
|
||||
const EMBEDDED_FILES* aEmbeddedFiles = nullptr );
|
||||
|
||||
/// cache entries
|
||||
std::list< S3D_CACHE_ENTRY* > m_CacheList;
|
||||
|
@ -156,7 +156,7 @@ void EDA_3D_MODEL_VIEWER::Set3DModel( const wxString& aModelPathName)
|
||||
|
||||
if( m_cacheManager )
|
||||
{
|
||||
const S3DMODEL* model = m_cacheManager->GetModel( aModelPathName, wxEmptyString );
|
||||
const S3DMODEL* model = m_cacheManager->GetModel( aModelPathName, wxEmptyString, nullptr );
|
||||
|
||||
if( model )
|
||||
Set3DModel( (const S3DMODEL &)*model );
|
||||
|
@ -66,7 +66,9 @@ public:
|
||||
/**
|
||||
* Set this model to be displayed.
|
||||
*
|
||||
* @param aModelPathName 3D model path name.
|
||||
* N.B. This will not load a model from the internal cache. Only from on disk.
|
||||
*
|
||||
* @param aModelPathName 3D model path name. Must be a file on disk.
|
||||
*/
|
||||
void Set3DModel( const wxString& aModelPathName );
|
||||
|
||||
|
@ -974,7 +974,7 @@ void RENDER_3D_OPENGL::load3dModels( REPORTER* aStatusReporter )
|
||||
{
|
||||
// It is not present, try get it from cache
|
||||
const S3DMODEL* modelPtr =
|
||||
m_boardAdapter.Get3dCacheManager()->GetModel( fp_model.m_Filename, footprintBasePath );
|
||||
m_boardAdapter.Get3dCacheManager()->GetModel( fp_model.m_Filename, footprintBasePath, footprint );
|
||||
|
||||
// only add it if the return is not NULL
|
||||
if( modelPtr )
|
||||
|
@ -1247,8 +1247,6 @@ void RENDER_3D_RAYTRACE_BASE::load3DModels( CONTAINER_3D& aDstContainer, bool aS
|
||||
|
||||
// Get the list of model files for this model
|
||||
S3D_CACHE* cacheMgr = m_boardAdapter.Get3dCacheManager();
|
||||
auto sM = fp->Models().begin();
|
||||
auto eM = fp->Models().end();
|
||||
|
||||
wxString libraryName = fp->GetFPID().GetLibNickname();
|
||||
|
||||
@ -1271,44 +1269,38 @@ void RENDER_3D_RAYTRACE_BASE::load3DModels( CONTAINER_3D& aDstContainer, bool aS
|
||||
}
|
||||
}
|
||||
|
||||
while( sM != eM )
|
||||
for( FP_3DMODEL& model : fp->Models() )
|
||||
{
|
||||
if( ( static_cast<float>( sM->m_Opacity ) > FLT_EPSILON )
|
||||
&& ( sM->m_Show && !sM->m_Filename.empty() ) )
|
||||
// get it from cache
|
||||
const S3DMODEL* modelPtr =
|
||||
cacheMgr->GetModel( model.m_Filename, footprintBasePath, fp );
|
||||
|
||||
// only add it if the return is not NULL.
|
||||
if( modelPtr )
|
||||
{
|
||||
// get it from cache
|
||||
const S3DMODEL* modelPtr =
|
||||
cacheMgr->GetModel( sM->m_Filename, footprintBasePath );
|
||||
glm::mat4 modelMatrix = fpMatrix;
|
||||
|
||||
// only add it if the return is not NULL.
|
||||
if( modelPtr )
|
||||
{
|
||||
glm::mat4 modelMatrix = fpMatrix;
|
||||
modelMatrix = glm::translate( modelMatrix,
|
||||
SFVEC3F( model.m_Offset.x, model.m_Offset.y, model.m_Offset.z ) );
|
||||
|
||||
modelMatrix = glm::translate( modelMatrix,
|
||||
SFVEC3F( sM->m_Offset.x, sM->m_Offset.y, sM->m_Offset.z ) );
|
||||
modelMatrix = glm::rotate( modelMatrix,
|
||||
(float) -( model.m_Rotation.z / 180.0f ) * glm::pi<float>(),
|
||||
SFVEC3F( 0.0f, 0.0f, 1.0f ) );
|
||||
|
||||
modelMatrix = glm::rotate( modelMatrix,
|
||||
(float) -( sM->m_Rotation.z / 180.0f ) * glm::pi<float>(),
|
||||
SFVEC3F( 0.0f, 0.0f, 1.0f ) );
|
||||
modelMatrix = glm::rotate( modelMatrix,
|
||||
(float) -( model.m_Rotation.y / 180.0f ) * glm::pi<float>(),
|
||||
SFVEC3F( 0.0f, 1.0f, 0.0f ) );
|
||||
|
||||
modelMatrix = glm::rotate( modelMatrix,
|
||||
(float) -( sM->m_Rotation.y / 180.0f ) * glm::pi<float>(),
|
||||
SFVEC3F( 0.0f, 1.0f, 0.0f ) );
|
||||
modelMatrix = glm::rotate( modelMatrix,
|
||||
(float) -( model.m_Rotation.x / 180.0f ) * glm::pi<float>(),
|
||||
SFVEC3F( 1.0f, 0.0f, 0.0f ) );
|
||||
|
||||
modelMatrix = glm::rotate( modelMatrix,
|
||||
(float) -( sM->m_Rotation.x / 180.0f ) * glm::pi<float>(),
|
||||
SFVEC3F( 1.0f, 0.0f, 0.0f ) );
|
||||
modelMatrix = glm::scale( modelMatrix,
|
||||
SFVEC3F( model.m_Scale.x, model.m_Scale.y, model.m_Scale.z ) );
|
||||
|
||||
modelMatrix = glm::scale( modelMatrix,
|
||||
SFVEC3F( sM->m_Scale.x, sM->m_Scale.y, sM->m_Scale.z ) );
|
||||
|
||||
addModels( aDstContainer, modelPtr, modelMatrix, (float) sM->m_Opacity,
|
||||
aSkipMaterialInformation, boardItem );
|
||||
}
|
||||
addModels( aDstContainer, modelPtr, modelMatrix, (float) model.m_Opacity,
|
||||
aSkipMaterialInformation, boardItem );
|
||||
}
|
||||
|
||||
++sM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -91,7 +91,6 @@ set(3D-VIEWER_SRCS
|
||||
common_ogl/ogl_utils.cpp
|
||||
3d_fastmath.cpp
|
||||
3d_math.cpp
|
||||
dialogs/3d_cache_dialogs.cpp
|
||||
dialogs/appearance_controls_3D.cpp
|
||||
dialogs/appearance_controls_3D_base.cpp
|
||||
dialogs/dialog_select_3d_model_base.cpp
|
||||
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2020-2021 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 2
|
||||
* 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/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <dialogs/dialog_configure_paths.h>
|
||||
|
||||
#include "3d_info.h"
|
||||
#include "3d_cache.h"
|
||||
#include "3d_cache_dialogs.h"
|
||||
#include "dialog_select_3d_model.h"
|
||||
|
||||
|
||||
bool S3D::Select3DModel( wxWindow* aParent, S3D_CACHE* aCache, wxString& prevModelSelectDir,
|
||||
int& prevModelWildcard, FP_3DMODEL* aModel )
|
||||
{
|
||||
if( nullptr == aModel )
|
||||
return false;
|
||||
|
||||
DIALOG_SELECT_3DMODEL dm( aParent, aCache, aModel, prevModelSelectDir, prevModelWildcard );
|
||||
|
||||
// Use QuasiModal so that Configure3DPaths (and its help window) will work
|
||||
return dm.ShowQuasiModal() == wxID_OK;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::Configure3DPaths( wxWindow* aParent, FILENAME_RESOLVER* aResolver )
|
||||
{
|
||||
DIALOG_CONFIGURE_PATHS dlg( aParent );
|
||||
|
||||
// Use QuasiModal so that HTML help window will work
|
||||
return( dlg.ShowQuasiModal() == wxID_OK );
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* 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 2
|
||||
* 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/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef CACHE_DIALOGS_3D_H
|
||||
#define CACHE_DIALOGS_3D_H
|
||||
|
||||
#include <wx/window.h>
|
||||
|
||||
class S3D_CACHE;
|
||||
class FILENAME_RESOLVER;
|
||||
|
||||
namespace S3D
|
||||
{
|
||||
bool Select3DModel( wxWindow* aParent, S3D_CACHE* aCache, wxString& prevModelSelectDir,
|
||||
int& prevModelWildcard, FP_3DMODEL* aModel );
|
||||
|
||||
bool Configure3DPaths( wxWindow* aParent, FILENAME_RESOLVER* aResolver );
|
||||
}
|
||||
|
||||
#endif // CACHE_DIALOGS_3D_H
|
@ -29,9 +29,9 @@
|
||||
#include "project.h"
|
||||
#include "3d_cache/3d_info.h"
|
||||
#include "3d_cache/3d_cache.h"
|
||||
#include "3d_cache_dialogs.h"
|
||||
#include <3d_model_viewer/eda_3d_model_viewer.h>
|
||||
#include <common_ogl/ogl_attr_list.h>
|
||||
#include <dialogs/dialog_configure_paths.h>
|
||||
#include <filename_resolver.h>
|
||||
#include <pcbnew/footprint.h>
|
||||
#include <wx_filename.h>
|
||||
@ -197,7 +197,9 @@ void DIALOG_SELECT_3DMODEL::SetRootDir( wxCommandEvent& event )
|
||||
|
||||
void DIALOG_SELECT_3DMODEL::Cfg3DPaths( wxCommandEvent& event )
|
||||
{
|
||||
if( S3D::Configure3DPaths( this, m_resolver ) )
|
||||
DIALOG_CONFIGURE_PATHS dlg( this );
|
||||
|
||||
if( dlg.ShowQuasiModal() == wxID_OK )
|
||||
updateDirChoiceList();
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,11 @@ public:
|
||||
void SetRootDir( wxCommandEvent& event ) override;
|
||||
void Cfg3DPaths( wxCommandEvent& event ) override;
|
||||
|
||||
bool IsEmbedded3DModel() const
|
||||
{
|
||||
return m_EmbedModelCb->IsChecked();
|
||||
}
|
||||
|
||||
private:
|
||||
void updateDirChoiceList( void );
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
|
||||
// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf0)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@ -35,6 +35,12 @@ DIALOG_SELECT_3D_MODEL_BASE::DIALOG_SELECT_3D_MODEL_BASE( wxWindow* parent, wxWi
|
||||
|
||||
bSizerLeft->Add( m_FileTree, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* bSizer7;
|
||||
bSizer7 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
|
||||
bSizerLeft->Add( bSizer7, 0, wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_panelLeft->SetSizer( bSizerLeft );
|
||||
m_panelLeft->Layout();
|
||||
@ -70,6 +76,15 @@ DIALOG_SELECT_3D_MODEL_BASE::DIALOG_SELECT_3D_MODEL_BASE( wxWindow* parent, wxWi
|
||||
|
||||
bSizerMain->Add( bSizerLower, 0, wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* bSizer6;
|
||||
bSizer6 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_EmbedModelCb = new wxCheckBox( this, wxID_ANY, _("Embed Model"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizer6->Add( m_EmbedModelCb, 0, wxALL, 5 );
|
||||
|
||||
|
||||
bSizer6->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
m_sdbSizer = new wxStdDialogButtonSizer();
|
||||
m_sdbSizerOK = new wxButton( this, wxID_OK );
|
||||
m_sdbSizer->AddButton( m_sdbSizerOK );
|
||||
@ -77,7 +92,10 @@ DIALOG_SELECT_3D_MODEL_BASE::DIALOG_SELECT_3D_MODEL_BASE( wxWindow* parent, wxWi
|
||||
m_sdbSizer->AddButton( m_sdbSizerCancel );
|
||||
m_sdbSizer->Realize();
|
||||
|
||||
bSizerMain->Add( m_sdbSizer, 0, wxEXPAND|wxALL, 5 );
|
||||
bSizer6->Add( m_sdbSizer, 0, wxEXPAND|wxALL, 5 );
|
||||
|
||||
|
||||
bSizerMain->Add( bSizer6, 0, wxEXPAND, 5 );
|
||||
|
||||
|
||||
this->SetSizer( bSizerMain );
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
|
||||
// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf0)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
@ -26,6 +26,7 @@
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/icon.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/dialog.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@ -47,6 +48,7 @@ class DIALOG_SELECT_3D_MODEL_BASE : public DIALOG_SHIM
|
||||
wxStaticText* m_stDirChoice;
|
||||
wxChoice* m_dirChoices;
|
||||
wxButton* m_cfgPathsButt;
|
||||
wxCheckBox* m_EmbedModelCb;
|
||||
wxStdDialogButtonSizer* m_sdbSizer;
|
||||
wxButton* m_sdbSizerOK;
|
||||
wxButton* m_sdbSizerCancel;
|
||||
|
@ -92,6 +92,12 @@ public:
|
||||
*/
|
||||
void UpdateDummyFootprint( bool aRelaodRequired = true );
|
||||
|
||||
/**
|
||||
* Get the dummy footprint that is used for previewing the 3D model.
|
||||
* We use this to hold the temporary 3D model shapes.
|
||||
*/
|
||||
FOOTPRINT* GetDummyFootprint() const { return m_dummyFootprint; }
|
||||
|
||||
private:
|
||||
/**
|
||||
* Load 3D relevant settings from the user configuration
|
||||
|
@ -809,6 +809,11 @@ include_directories( SYSTEM ${GLM_INCLUDE_DIR} )
|
||||
#
|
||||
find_package(ZLIB REQUIRED)
|
||||
|
||||
#
|
||||
# Find Zstd library, required
|
||||
#
|
||||
find_package(ZSTD REQUIRED)
|
||||
|
||||
#
|
||||
# Find libcurl, required
|
||||
#
|
||||
|
@ -145,6 +145,7 @@ namespace ${enum}
|
||||
// these first few are negative special ones for syntax, and are
|
||||
// inherited from DSNLEXER.
|
||||
T_NONE = DSN_NONE,
|
||||
T_BAR = DSN_BAR, // Also called pipe: '|'
|
||||
T_COMMENT = DSN_COMMENT,
|
||||
T_STRING_QUOTE = DSN_STRING_QUOTE,
|
||||
T_QUOTE_DEF = DSN_QUOTE_DEF,
|
||||
|
41
cmake/FindZSTD.cmake
Normal file
41
cmake/FindZSTD.cmake
Normal file
@ -0,0 +1,41 @@
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
#
|
||||
# - Try to find Facebook zstd library
|
||||
# This will define
|
||||
# ZSTD_FOUND
|
||||
# ZSTD_INCLUDE_DIR
|
||||
# ZSTD_LIBRARY
|
||||
#
|
||||
|
||||
find_path(ZSTD_INCLUDE_DIR NAMES zstd.h)
|
||||
|
||||
find_library(ZSTD_LIBRARY_DEBUG NAMES zstdd zstd_staticd)
|
||||
find_library(ZSTD_LIBRARY_RELEASE NAMES zstd zstd_static)
|
||||
|
||||
include(SelectLibraryConfigurations)
|
||||
SELECT_LIBRARY_CONFIGURATIONS(ZSTD)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(
|
||||
ZSTD DEFAULT_MSG
|
||||
ZSTD_LIBRARY ZSTD_INCLUDE_DIR
|
||||
)
|
||||
|
||||
if (ZSTD_FOUND)
|
||||
message(STATUS "Found Zstd: ${ZSTD_LIBRARY}")
|
||||
endif()
|
||||
|
||||
mark_as_advanced(ZSTD_INCLUDE_DIR ZSTD_LIBRARY)
|
@ -195,6 +195,8 @@ target_link_libraries( kicommon
|
||||
nlohmann_json
|
||||
fmt::fmt
|
||||
CURL::libcurl
|
||||
picosha2
|
||||
zstd
|
||||
${wxWidgets_LIBRARIES}
|
||||
${LIBGIT2_LIBRARIES}
|
||||
|
||||
@ -267,6 +269,7 @@ target_include_directories( kicommon
|
||||
$<TARGET_PROPERTY:pegtl,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:expected,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:kiapi,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:picosha2,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
)
|
||||
|
||||
add_dependencies( kicommon pegtl version_header )
|
||||
@ -304,6 +307,7 @@ set( COMMON_DLG_SRCS
|
||||
dialogs/dialog_configure_paths_base.cpp
|
||||
dialogs/dialog_display_html_text_base.cpp
|
||||
dialogs/dialog_edit_library_tables.cpp
|
||||
dialogs/dialog_embed_files.cpp
|
||||
dialogs/dialog_global_lib_table_config.cpp
|
||||
dialogs/dialog_global_lib_table_config_base.cpp
|
||||
dialogs/dialog_grid_settings.cpp
|
||||
@ -338,6 +342,8 @@ set( COMMON_DLG_SRCS
|
||||
dialogs/panel_color_settings.cpp
|
||||
dialogs/panel_common_settings.cpp
|
||||
dialogs/panel_common_settings_base.cpp
|
||||
dialogs/panel_embedded_files.cpp
|
||||
dialogs/panel_embedded_files_base.cpp
|
||||
dialogs/panel_gal_display_options.cpp
|
||||
dialogs/panel_hotkeys_editor.cpp
|
||||
dialogs/panel_image_editor.cpp
|
||||
@ -534,6 +540,7 @@ set( COMMON_SRCS
|
||||
eda_shape.cpp
|
||||
eda_text.cpp
|
||||
eda_tools.cpp
|
||||
embedded_files.cpp
|
||||
env_paths.cpp
|
||||
executable_names.cpp
|
||||
filename_resolver.cpp
|
||||
@ -589,6 +596,7 @@ set( COMMON_SRCS
|
||||
tool/edit_constraints.cpp
|
||||
tool/edit_points.cpp
|
||||
tool/editor_conditions.cpp
|
||||
tool/embed_tool.cpp
|
||||
tool/grid_helper.cpp
|
||||
tool/grid_menu.cpp
|
||||
tool/picker_tool.cpp
|
||||
@ -921,6 +929,17 @@ make_lexer_export(
|
||||
kicommon.h
|
||||
)
|
||||
|
||||
# auto-generate embedded files lexer and keywords
|
||||
make_lexer_export(
|
||||
kicommon
|
||||
embedded_files.keywords
|
||||
embedded_files_lexer.h
|
||||
embedded_files_keywords.cpp
|
||||
EMBEDDED_FILES_T
|
||||
KICOMMON_API
|
||||
kicommon.h
|
||||
)
|
||||
|
||||
# This one gets made only when testing.
|
||||
# to build it, first enable #define STAND_ALONE at top of dsnlexer.cpp
|
||||
add_executable( dsntest EXCLUDE_FROM_ALL dsnlexer.cpp )
|
||||
|
78
common/dialogs/dialog_embed_files.cpp
Normal file
78
common/dialogs/dialog_embed_files.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 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/>.
|
||||
*/
|
||||
|
||||
#include <wx/button.h>
|
||||
#include <wx/sizer.h>
|
||||
|
||||
#include <dialogs/dialog_embed_files.h>
|
||||
|
||||
|
||||
DIALOG_EMBED_FILES::DIALOG_EMBED_FILES( wxWindow* aParent, const wxString& aTitle ) :
|
||||
DIALOG_SHIM( aParent, wxID_ANY, aTitle, wxDefaultPosition, wxDefaultSize,
|
||||
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ),
|
||||
m_contentPanel( nullptr )
|
||||
{
|
||||
// Construction delayed until after panel is installed
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_EMBED_FILES::InstallPanel( wxPanel* aPanel )
|
||||
{
|
||||
m_contentPanel = aPanel;
|
||||
|
||||
// Now perform the body of the constructor
|
||||
auto mainSizer = new wxBoxSizer( wxVERTICAL );
|
||||
SetSizer( mainSizer );
|
||||
|
||||
mainSizer->Add( m_contentPanel, 1, wxEXPAND|wxLEFT|wxTOP|wxRIGHT, 5 );
|
||||
m_contentPanel->SetMinSize( FromDIP( wxSize( 1000, 600 ) ) );
|
||||
|
||||
auto sdbSizer = new wxStdDialogButtonSizer();
|
||||
auto sdbSizerOK = new wxButton( this, wxID_OK );
|
||||
sdbSizer->AddButton( sdbSizerOK );
|
||||
auto sdbSizerCancel = new wxButton( this, wxID_CANCEL );
|
||||
sdbSizer->AddButton( sdbSizerCancel );
|
||||
sdbSizer->Realize();
|
||||
|
||||
mainSizer->Add( sdbSizer, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
SetupStandardButtons();
|
||||
|
||||
finishDialogSettings();
|
||||
|
||||
// On some windows manager (Unity, XFCE), this dialog is not always raised, depending
|
||||
// on how the dialog is run.
|
||||
Raise();
|
||||
}
|
||||
|
||||
|
||||
bool DIALOG_EMBED_FILES::TransferDataToWindow()
|
||||
{
|
||||
return m_contentPanel->TransferDataToWindow();
|
||||
}
|
||||
|
||||
|
||||
bool DIALOG_EMBED_FILES::TransferDataFromWindow()
|
||||
{
|
||||
/**
|
||||
* N.B. *do not* call wxDialog::TransferDataFromWindow() in the dialog code.
|
||||
*/
|
||||
return m_contentPanel->TransferDataFromWindow();
|
||||
}
|
||||
|
@ -26,6 +26,8 @@
|
||||
#include <dialogs/dialog_page_settings.h>
|
||||
#include <eda_draw_frame.h>
|
||||
#include <eda_item.h>
|
||||
#include <embedded_files.h>
|
||||
#include <filename_resolver.h>
|
||||
#include <gr_basic.h>
|
||||
#include <kiface_base.h>
|
||||
#include <macros.h>
|
||||
@ -38,6 +40,7 @@
|
||||
#include <drawing_sheet/ds_painter.h>
|
||||
#include <string_utils.h>
|
||||
#include <widgets/std_bitmap_button.h>
|
||||
#include <widgets/filedlg_open_embed_file.h>
|
||||
#include <wx/valgen.h>
|
||||
#include <wx/tokenzr.h>
|
||||
#include <wx/filedlg.h>
|
||||
@ -75,7 +78,7 @@ static const wxString pageFmts[] =
|
||||
// to be recognized in code
|
||||
};
|
||||
|
||||
DIALOG_PAGES_SETTINGS::DIALOG_PAGES_SETTINGS( EDA_DRAW_FRAME* aParent, double aIuPerMils,
|
||||
DIALOG_PAGES_SETTINGS::DIALOG_PAGES_SETTINGS( EDA_DRAW_FRAME* aParent, EMBEDDED_FILES* aEmbeddedFiles, double aIuPerMils,
|
||||
const VECTOR2D& aMaxUserSizeMils ) :
|
||||
DIALOG_PAGES_SETTINGS_BASE( aParent ),
|
||||
m_parent( aParent ),
|
||||
@ -83,6 +86,7 @@ DIALOG_PAGES_SETTINGS::DIALOG_PAGES_SETTINGS( EDA_DRAW_FRAME* aParent, double aI
|
||||
m_initialized( false ),
|
||||
m_pageBitmap( nullptr ),
|
||||
m_iuPerMils( aIuPerMils ),
|
||||
m_embeddedFiles( aEmbeddedFiles ),
|
||||
m_customSizeX( aParent, m_userSizeXLabel, m_userSizeXCtrl, m_userSizeXUnits ),
|
||||
m_customSizeY( aParent, m_userSizeYLabel, m_userSizeYCtrl, m_userSizeYUnits )
|
||||
{
|
||||
@ -114,6 +118,10 @@ DIALOG_PAGES_SETTINGS::DIALOG_PAGES_SETTINGS( EDA_DRAW_FRAME* aParent, double aI
|
||||
m_staticTextTitleBlock->SetLabel( _( "Title Block" ) );
|
||||
}
|
||||
|
||||
m_filenameResolver = new FILENAME_RESOLVER;
|
||||
m_filenameResolver->SetProject( &Prj() );
|
||||
m_filenameResolver->SetProgramBase( &Pgm() );
|
||||
|
||||
SetupStandardButtons();
|
||||
|
||||
Centre();
|
||||
@ -467,7 +475,8 @@ bool DIALOG_PAGES_SETTINGS::SavePageSettings()
|
||||
|
||||
if( fileName != BASE_SCREEN::m_DrawingSheetFileName )
|
||||
{
|
||||
wxString fullFileName = DS_DATA_MODEL::ResolvePath( fileName, m_projectPath );
|
||||
|
||||
wxString fullFileName = m_filenameResolver->ResolvePath( fileName, m_projectPath, m_embeddedFiles );
|
||||
|
||||
BASE_SCREEN::m_DrawingSheetFileName = fileName;
|
||||
|
||||
@ -794,19 +803,30 @@ void DIALOG_PAGES_SETTINGS::OnWksFileSelection( wxCommandEvent& event )
|
||||
}
|
||||
|
||||
// Display a file picker dialog
|
||||
FILEDLG_OPEN_EMBED_FILE customize;
|
||||
wxFileDialog fileDialog( this, _( "Drawing Sheet File" ), path, name,
|
||||
FILEEXT::DrawingSheetFileWildcard(),
|
||||
wxFD_DEFAULT_STYLE | wxFD_FILE_MUST_EXIST );
|
||||
|
||||
if( m_embeddedFiles )
|
||||
fileDialog.SetCustomizeHook( customize );
|
||||
|
||||
if( fileDialog.ShowModal() != wxID_OK )
|
||||
return;
|
||||
|
||||
wxString fileName = fileDialog.GetPath();
|
||||
wxString shortFileName;
|
||||
|
||||
// Try to use a project-relative path first:
|
||||
if( !m_projectPath.IsEmpty() && fileName.StartsWith( m_projectPath ) )
|
||||
if( m_embeddedFiles && customize.GetEmbed() )
|
||||
{
|
||||
fn.Assign( fileName );
|
||||
EMBEDDED_FILES::EMBEDDED_FILE* result = m_embeddedFiles->AddFile( fn, false );
|
||||
shortFileName = result->GetLink();
|
||||
fileName = m_embeddedFiles->GetTempFileName( result->name ).GetFullPath();
|
||||
}
|
||||
else if( !m_projectPath.IsEmpty() && fileName.StartsWith( m_projectPath ) )
|
||||
{
|
||||
// Try to use a project-relative path
|
||||
fn = wxFileName( fileName );
|
||||
fn.MakeRelativeTo( m_projectPath );
|
||||
shortFileName = fn.GetFullPath();
|
||||
|
314
common/dialogs/panel_embedded_files.cpp
Normal file
314
common/dialogs/panel_embedded_files.cpp
Normal file
@ -0,0 +1,314 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 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, 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
|
||||
*/
|
||||
|
||||
#include <bitmaps.h>
|
||||
#include <dialogs/panel_embedded_files.h>
|
||||
#include <embedded_files.h>
|
||||
#include <kidialog.h>
|
||||
#include <widgets/std_bitmap_button.h>
|
||||
#include <widgets/wx_grid.h>
|
||||
|
||||
#include <wx/clipbrd.h>
|
||||
#include <wx/dirdlg.h>
|
||||
#include <wx/ffile.h>
|
||||
#include <wx/filedlg.h>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/menu.h>
|
||||
|
||||
PANEL_EMBEDDED_FILES::PANEL_EMBEDDED_FILES( wxWindow* parent, EMBEDDED_FILES* aFiles ) :
|
||||
PANEL_EMBEDDED_FILES_BASE( parent ),
|
||||
m_files( aFiles )
|
||||
{
|
||||
m_localFiles = new EMBEDDED_FILES();
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
void PANEL_EMBEDDED_FILES::onGridRightClick( wxGridEvent& event )
|
||||
{
|
||||
wxMenu menu;
|
||||
menu.Append( wxID_COPY, _( "Copy Embedded Reference" ) );
|
||||
|
||||
menu.Bind( wxEVT_COMMAND_MENU_SELECTED,
|
||||
[&]( wxCommandEvent& )
|
||||
{
|
||||
int row = event.GetRow();
|
||||
if( row >= 0 && row < m_files_grid->GetNumberRows() )
|
||||
{
|
||||
wxString cellValue = m_files_grid->GetCellValue( row, 1 );
|
||||
|
||||
if( wxTheClipboard->Open() )
|
||||
{
|
||||
wxTheClipboard->SetData( new wxTextDataObject( cellValue ) );
|
||||
wxTheClipboard->Close();
|
||||
}
|
||||
}
|
||||
}, wxID_COPY );
|
||||
|
||||
PopupMenu( &menu );
|
||||
}
|
||||
|
||||
|
||||
bool PANEL_EMBEDDED_FILES::TransferDataToWindow()
|
||||
{
|
||||
m_files_grid->ClearGrid();
|
||||
|
||||
if( m_files_grid->GetNumberRows() > 0 )
|
||||
m_files_grid->DeleteRows( 0, m_files_grid->GetNumberRows() );
|
||||
|
||||
int ii = 0;
|
||||
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()
|
||||
{
|
||||
m_files->ClearEmbeddedFiles();
|
||||
|
||||
std::vector<EMBEDDED_FILES::EMBEDDED_FILE*> files;
|
||||
|
||||
for( auto it = m_localFiles->EmbeddedFileMap().begin(); it != m_localFiles->EmbeddedFileMap().end(); it++ )
|
||||
files.push_back( it->second );
|
||||
|
||||
for( auto& file : files )
|
||||
{
|
||||
m_files->AddFile( file );
|
||||
m_localFiles->RemoveFile( file->name, false );
|
||||
}
|
||||
|
||||
m_files->SetAreFontsEmbedded( m_cbEmbedFonts->IsChecked() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_EMBEDDED_FILES::onAddEmbeddedFile( wxCommandEvent& event )
|
||||
{
|
||||
wxFileDialog fileDialog( this, _( "Select a file to embed" ), wxEmptyString, wxEmptyString,
|
||||
_( "All files|*.*" ), wxFD_OPEN | wxFD_FILE_MUST_EXIST );
|
||||
|
||||
if( fileDialog.ShowModal() == wxID_OK )
|
||||
{
|
||||
wxFileName fileName( fileDialog.GetPath() );
|
||||
wxString name = fileName.GetFullName();
|
||||
|
||||
if( m_localFiles->HasFile( name ) )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "File '%s' already exists." ),
|
||||
name );
|
||||
|
||||
KIDIALOG errorDlg( m_parent, msg, _( "Confirmation" ),
|
||||
wxOK | wxCANCEL | wxICON_WARNING );
|
||||
errorDlg.SetOKLabel( _( "Overwrite" ) );
|
||||
|
||||
if( errorDlg.ShowModal() != wxID_OK )
|
||||
return;
|
||||
|
||||
for( int ii = 0; ii < m_files_grid->GetNumberRows(); ii++ )
|
||||
{
|
||||
if( m_files_grid->GetCellValue( ii, 0 ) == name )
|
||||
{
|
||||
m_files_grid->DeleteRows( ii );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
m_files_grid->AppendRows( 1 );
|
||||
int ii = m_files_grid->GetNumberRows() - 1;
|
||||
m_files_grid->SetCellValue( ii, 0, name );
|
||||
m_files_grid->SetCellValue( ii, 1, result->GetLink() );
|
||||
}
|
||||
}
|
||||
|
||||
void PANEL_EMBEDDED_FILES::onDeleteEmbeddedFile( wxCommandEvent& event )
|
||||
{
|
||||
int row = m_files_grid->GetGridCursorRow();
|
||||
|
||||
if( row < 0 )
|
||||
return;
|
||||
|
||||
wxString name = m_files_grid->GetCellValue( row, 0 );
|
||||
|
||||
m_localFiles->RemoveFile( name );
|
||||
|
||||
m_files_grid->DeleteRows( row );
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
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() )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "File '%s' already exists." ),
|
||||
fileName.GetFullName() );
|
||||
|
||||
KIDIALOG errorDlg( m_parent, msg, _( "Confirmation" ),
|
||||
wxOK | wxCANCEL | wxICON_WARNING );
|
||||
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__
|
||||
wxString msg = wxString::Format( _( "Directory '%s' is not writable." ),
|
||||
fileName.GetFullName() );
|
||||
#else
|
||||
wxString msg = wxString::Format( _( "Folder '%s' is not writable." ),
|
||||
fileName.GetPath() );
|
||||
#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;
|
||||
|
||||
wxFFile ffile( fileName.GetFullPath(), wxT( "w" ) );
|
||||
|
||||
if( !ffile.IsOpened() )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Failed to open file '%s'." ),
|
||||
fileName.GetFullName() );
|
||||
|
||||
KIDIALOG errorDlg( m_parent, msg, _( "Error" ), wxOK | wxICON_ERROR );
|
||||
errorDlg.ShowModal();
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !ffile.Write( file->decompressedData.data(), file->decompressedData.size() ) )
|
||||
{
|
||||
wxString msg = wxString::Format( _( "Failed to write file '%s'." ),
|
||||
fileName.GetFullName() );
|
||||
|
||||
KIDIALOG errorDlg( m_parent, msg, _( "Error" ), wxOK | wxICON_ERROR );
|
||||
errorDlg.ShowModal();
|
||||
}
|
||||
}
|
||||
}
|
58
common/dialogs/panel_embedded_files.h
Normal file
58
common/dialogs/panel_embedded_files.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2023 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, 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
|
||||
*/
|
||||
|
||||
#ifndef PANEL_EMBEDDED_FILES_H
|
||||
#define PANEL_EMBEDDED_FILES_H
|
||||
|
||||
#include "panel_embedded_files_base.h"
|
||||
|
||||
class EMBEDDED_FILES;
|
||||
|
||||
class PANEL_EMBEDDED_FILES : public PANEL_EMBEDDED_FILES_BASE
|
||||
{
|
||||
public:
|
||||
PANEL_EMBEDDED_FILES( wxWindow* parent, EMBEDDED_FILES* aFiles );
|
||||
~PANEL_EMBEDDED_FILES() override {};
|
||||
|
||||
bool TransferDataFromWindow() override;
|
||||
bool TransferDataToWindow() override;
|
||||
bool GetEmbedFonts() const { return m_cbEmbedFonts->GetValue(); }
|
||||
|
||||
protected:
|
||||
|
||||
void onGridRightClick( wxGridEvent& event ) override;
|
||||
void onAddEmbeddedFile( wxCommandEvent& event ) override;
|
||||
void onDeleteEmbeddedFile( wxCommandEvent& event ) override;
|
||||
void onExportFiles( wxCommandEvent& event ) override;
|
||||
void onSize( wxSizeEvent& event ) override;
|
||||
|
||||
private:
|
||||
|
||||
void resizeGrid();
|
||||
|
||||
EMBEDDED_FILES* m_files;
|
||||
EMBEDDED_FILES* m_localFiles;
|
||||
};
|
||||
|
||||
|
||||
#endif // PANEL_EMBEDDED_FILES_H
|
118
common/dialogs/panel_embedded_files_base.cpp
Normal file
118
common/dialogs/panel_embedded_files_base.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6a-dirty)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "widgets/std_bitmap_button.h"
|
||||
#include "widgets/wx_grid.h"
|
||||
|
||||
#include "panel_embedded_files_base.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PANEL_EMBEDDED_FILES_BASE::PANEL_EMBEDDED_FILES_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
|
||||
{
|
||||
wxBoxSizer* bMainSizer;
|
||||
bMainSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxBoxSizer* m_global_sizer;
|
||||
m_global_sizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_files_grid = new WX_GRID( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
|
||||
// Grid
|
||||
m_files_grid->CreateGrid( 1, 2 );
|
||||
m_files_grid->EnableEditing( false );
|
||||
m_files_grid->EnableGridLines( true );
|
||||
m_files_grid->EnableDragGridSize( false );
|
||||
m_files_grid->SetMargins( 0, 0 );
|
||||
|
||||
// Columns
|
||||
m_files_grid->SetColSize( 0, 440 );
|
||||
m_files_grid->SetColSize( 1, 180 );
|
||||
m_files_grid->EnableDragColMove( false );
|
||||
m_files_grid->EnableDragColSize( true );
|
||||
m_files_grid->SetColLabelValue( 0, _("Filename") );
|
||||
m_files_grid->SetColLabelValue( 1, _("Internal Reference") );
|
||||
m_files_grid->SetColLabelSize( 22 );
|
||||
m_files_grid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
|
||||
|
||||
// Rows
|
||||
m_files_grid->AutoSizeRows();
|
||||
m_files_grid->EnableDragRowSize( false );
|
||||
m_files_grid->SetRowLabelSize( 0 );
|
||||
m_files_grid->SetRowLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
|
||||
|
||||
// Label Appearance
|
||||
|
||||
// Cell Defaults
|
||||
m_files_grid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_CENTER );
|
||||
m_global_sizer->Add( m_files_grid, 5, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
bMainSizer->Add( m_global_sizer, 1, wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* bButtonsSizer;
|
||||
bButtonsSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_browse_button = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
|
||||
m_browse_button->SetToolTip( _("Add embedded file") );
|
||||
|
||||
bButtonsSizer->Add( m_browse_button, 0, wxTOP|wxBOTTOM|wxRIGHT, 5 );
|
||||
|
||||
|
||||
bButtonsSizer->Add( 20, 0, 0, wxEXPAND, 5 );
|
||||
|
||||
m_delete_button = new STD_BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
|
||||
m_delete_button->SetToolTip( _("Remove embedded file") );
|
||||
|
||||
bButtonsSizer->Add( m_delete_button, 0, wxTOP|wxBOTTOM|wxRIGHT, 5 );
|
||||
|
||||
|
||||
bButtonsSizer->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
m_export = new wxButton( this, wxID_ANY, _("&Export"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bButtonsSizer->Add( m_export, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
|
||||
|
||||
|
||||
bMainSizer->Add( bButtonsSizer, 0, wxEXPAND|wxALL, 3 );
|
||||
|
||||
m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
bMainSizer->Add( m_staticline1, 0, wxEXPAND | wxALL, 5 );
|
||||
|
||||
wxBoxSizer* bSizer4;
|
||||
bSizer4 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_cbEmbedFonts = new wxCheckBox( this, wxID_ANY, _("Embed Fonts"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_cbEmbedFonts->SetToolTip( _("Store a copy of all fonts used") );
|
||||
|
||||
bSizer4->Add( m_cbEmbedFonts, 0, wxALL, 5 );
|
||||
|
||||
|
||||
bMainSizer->Add( bSizer4, 0, wxEXPAND, 5 );
|
||||
|
||||
|
||||
this->SetSizer( bMainSizer );
|
||||
this->Layout();
|
||||
bMainSizer->Fit( this );
|
||||
|
||||
// Connect Events
|
||||
this->Connect( wxEVT_SIZE, wxSizeEventHandler( PANEL_EMBEDDED_FILES_BASE::onSize ) );
|
||||
m_files_grid->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( PANEL_EMBEDDED_FILES_BASE::onGridRightClick ), NULL, this );
|
||||
m_browse_button->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_EMBEDDED_FILES_BASE::onAddEmbeddedFile ), NULL, this );
|
||||
m_delete_button->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_EMBEDDED_FILES_BASE::onDeleteEmbeddedFile ), NULL, this );
|
||||
m_export->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_EMBEDDED_FILES_BASE::onExportFiles ), NULL, this );
|
||||
}
|
||||
|
||||
PANEL_EMBEDDED_FILES_BASE::~PANEL_EMBEDDED_FILES_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
this->Disconnect( wxEVT_SIZE, wxSizeEventHandler( PANEL_EMBEDDED_FILES_BASE::onSize ) );
|
||||
m_files_grid->Disconnect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( PANEL_EMBEDDED_FILES_BASE::onGridRightClick ), NULL, this );
|
||||
m_browse_button->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_EMBEDDED_FILES_BASE::onAddEmbeddedFile ), NULL, this );
|
||||
m_delete_button->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_EMBEDDED_FILES_BASE::onDeleteEmbeddedFile ), NULL, this );
|
||||
m_export->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_EMBEDDED_FILES_BASE::onExportFiles ), NULL, this );
|
||||
|
||||
}
|
559
common/dialogs/panel_embedded_files_base.fbp
Normal file
559
common/dialogs/panel_embedded_files_base.fbp
Normal file
@ -0,0 +1,559 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<wxFormBuilder_Project>
|
||||
<FileVersion major="1" minor="18"/>
|
||||
<object class="Project" expanded="true">
|
||||
<property name="code_generation">C++</property>
|
||||
<property name="cpp_class_decoration"></property>
|
||||
<property name="cpp_disconnect_events">1</property>
|
||||
<property name="cpp_event_generation">connect</property>
|
||||
<property name="cpp_help_provider">none</property>
|
||||
<property name="cpp_namespace"></property>
|
||||
<property name="cpp_precompiled_header"></property>
|
||||
<property name="cpp_use_array_enum">0</property>
|
||||
<property name="cpp_use_enum">0</property>
|
||||
<property name="embedded_files_path">res</property>
|
||||
<property name="encoding">UTF-8</property>
|
||||
<property name="file">panel_embedded_files_base</property>
|
||||
<property name="first_id">1000</property>
|
||||
<property name="internationalize">1</property>
|
||||
<property name="lua_skip_events">1</property>
|
||||
<property name="lua_ui_table">UI</property>
|
||||
<property name="name">panel_embedded_files</property>
|
||||
<property name="path">.</property>
|
||||
<property name="php_disconnect_events">0</property>
|
||||
<property name="php_disconnect_mode">source_name</property>
|
||||
<property name="php_skip_events">1</property>
|
||||
<property name="python_disconnect_events">0</property>
|
||||
<property name="python_disconnect_mode">source_name</property>
|
||||
<property name="python_image_path_wrapper_function_name"></property>
|
||||
<property name="python_indent_with_spaces"></property>
|
||||
<property name="python_skip_events">1</property>
|
||||
<property name="relative_path">1</property>
|
||||
<property name="use_microsoft_bom">0</property>
|
||||
<property name="use_native_eol">0</property>
|
||||
<object class="Panel" expanded="true">
|
||||
<property name="aui_managed">0</property>
|
||||
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
|
||||
<property name="bg"></property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="event_handler">impl_virtual</property>
|
||||
<property name="fg"></property>
|
||||
<property name="font"></property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="minimum_size">-1,-1</property>
|
||||
<property name="name">PANEL_EMBEDDED_FILES_BASE</property>
|
||||
<property name="pos"></property>
|
||||
<property name="size">-1,-1</property>
|
||||
<property name="subclass">; forward_declare</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="two_step_creation">0</property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style">wxTAB_TRAVERSAL</property>
|
||||
<event name="OnSize">onSize</event>
|
||||
<object class="wxBoxSizer" expanded="true">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bMainSizer</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxBoxSizer" expanded="false">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">m_global_sizer</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL|wxEXPAND</property>
|
||||
<property name="proportion">5</property>
|
||||
<object class="wxGrid" expanded="false">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer">0</property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position">0</property>
|
||||
<property name="aui_row">0</property>
|
||||
<property name="autosize_cols">0</property>
|
||||
<property name="autosize_rows">1</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="cell_bg"></property>
|
||||
<property name="cell_font"></property>
|
||||
<property name="cell_horiz_alignment">wxALIGN_LEFT</property>
|
||||
<property name="cell_text"></property>
|
||||
<property name="cell_vert_alignment">wxALIGN_CENTER</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="col_label_horiz_alignment">wxALIGN_CENTER</property>
|
||||
<property name="col_label_size">22</property>
|
||||
<property name="col_label_values">"Filename" "Internal Reference"</property>
|
||||
<property name="col_label_vert_alignment">wxALIGN_CENTER</property>
|
||||
<property name="cols">2</property>
|
||||
<property name="column_sizes">440,180</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">1</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="drag_col_move">0</property>
|
||||
<property name="drag_col_size">1</property>
|
||||
<property name="drag_grid_size">0</property>
|
||||
<property name="drag_row_size">0</property>
|
||||
<property name="editing">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">0</property>
|
||||
<property name="font"></property>
|
||||
<property name="grid_line_color"></property>
|
||||
<property name="grid_lines">1</property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label_bg"></property>
|
||||
<property name="label_font"></property>
|
||||
<property name="label_text"></property>
|
||||
<property name="margin_height">0</property>
|
||||
<property name="margin_width">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size">-1,-1</property>
|
||||
<property name="moveable">0</property>
|
||||
<property name="name">m_files_grid</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Fixed</property>
|
||||
<property name="row_label_horiz_alignment">wxALIGN_CENTER</property>
|
||||
<property name="row_label_size">0</property>
|
||||
<property name="row_label_values"></property>
|
||||
<property name="row_label_vert_alignment">wxALIGN_CENTER</property>
|
||||
<property name="row_sizes"></property>
|
||||
<property name="rows">1</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="subclass">WX_GRID; widgets/wx_grid.h; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnGridCellRightClick">onGridRightClick</event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">3</property>
|
||||
<property name="flag">wxEXPAND|wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBoxSizer" expanded="false">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bButtonsSizer</property>
|
||||
<property name="orient">wxHORIZONTAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxTOP|wxBOTTOM|wxRIGHT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBitmapButton" expanded="false">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer">0</property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position">0</property>
|
||||
<property name="aui_row">0</property>
|
||||
<property name="auth_needed">0</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="bitmap"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="current"></property>
|
||||
<property name="default">0</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="disabled"></property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="focus"></property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Add Embedded File</property>
|
||||
<property name="margins"></property>
|
||||
<property name="markup">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_browse_button</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="position"></property>
|
||||
<property name="pressed"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size">-1,-1</property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip">Add embedded file</property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnButtonClick">onAddEmbeddedFile</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="spacer" expanded="false">
|
||||
<property name="height">0</property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="width">20</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxTOP|wxBOTTOM|wxRIGHT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBitmapButton" expanded="false">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer">0</property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position">0</property>
|
||||
<property name="aui_row">0</property>
|
||||
<property name="auth_needed">0</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="bitmap"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="current"></property>
|
||||
<property name="default">0</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="disabled"></property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="focus"></property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Delete SelectedFile</property>
|
||||
<property name="margins"></property>
|
||||
<property name="markup">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_delete_button</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="position"></property>
|
||||
<property name="pressed"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size">-1,-1</property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip">Remove embedded file</property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnButtonClick">onDeleteEmbeddedFile</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="spacer" expanded="false">
|
||||
<property name="height">0</property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="width">0</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="false">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxButton" expanded="false">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer">0</property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position">0</property>
|
||||
<property name="aui_row">0</property>
|
||||
<property name="auth_needed">0</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="bitmap"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="current"></property>
|
||||
<property name="default">0</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="disabled"></property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="focus"></property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">&Export</property>
|
||||
<property name="margins"></property>
|
||||
<property name="markup">0</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_export</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="position"></property>
|
||||
<property name="pressed"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnButtonClick">onExportFiles</event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND | wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticLine" expanded="true">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer">0</property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position">0</property>
|
||||
<property name="aui_row">0</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_staticline1</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style">wxLI_HORIZONTAL</property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBoxSizer" expanded="true">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bSizer4</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="true">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxCheckBox" expanded="true">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer">0</property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position">0</property>
|
||||
<property name="aui_row">0</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="checked">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="drag_accept_files">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Embed Fonts</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_cbEmbedFonts</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip">Store a copy of all fonts used</property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</wxFormBuilder_Project>
|
64
common/dialogs/panel_embedded_files_base.h
Normal file
64
common/dialogs/panel_embedded_files_base.h
Normal file
@ -0,0 +1,64 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6a-dirty)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <wx/artprov.h>
|
||||
#include <wx/xrc/xmlres.h>
|
||||
#include <wx/intl.h>
|
||||
class STD_BITMAP_BUTTON;
|
||||
class WX_GRID;
|
||||
|
||||
#include <wx/colour.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/string.h>
|
||||
#include <wx/font.h>
|
||||
#include <wx/grid.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/bmpbuttn.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/icon.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/statline.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/panel.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class PANEL_EMBEDDED_FILES_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class PANEL_EMBEDDED_FILES_BASE : public wxPanel
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
WX_GRID* m_files_grid;
|
||||
STD_BITMAP_BUTTON* m_browse_button;
|
||||
STD_BITMAP_BUTTON* m_delete_button;
|
||||
wxButton* m_export;
|
||||
wxStaticLine* m_staticline1;
|
||||
wxCheckBox* m_cbEmbedFonts;
|
||||
|
||||
// Virtual event handlers, override them in your derived class
|
||||
virtual void onSize( wxSizeEvent& event ) { event.Skip(); }
|
||||
virtual void onGridRightClick( wxGridEvent& event ) { event.Skip(); }
|
||||
virtual void onAddEmbeddedFile( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void onDeleteEmbeddedFile( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void onExportFiles( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
PANEL_EMBEDDED_FILES_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
|
||||
|
||||
~PANEL_EMBEDDED_FILES_BASE();
|
||||
|
||||
};
|
||||
|
@ -145,33 +145,3 @@ DS_DATA_ITEM* DS_DATA_MODEL::GetItem( unsigned aIdx ) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
const wxString DS_DATA_MODEL::ResolvePath( const wxString& aPath, const wxString& aProjectPath )
|
||||
{
|
||||
wxString fullFileName = ExpandEnvVarSubstitutions( aPath, nullptr );
|
||||
|
||||
if( fullFileName.IsEmpty() )
|
||||
return fullFileName;
|
||||
|
||||
wxFileName fn = fullFileName;
|
||||
|
||||
if( fn.IsAbsolute() )
|
||||
return fullFileName;
|
||||
|
||||
// the path is not absolute: search it in project path, and then in kicad valid paths
|
||||
if( !aProjectPath.IsEmpty() )
|
||||
{
|
||||
fn.MakeAbsolute( aProjectPath );
|
||||
|
||||
if( wxFileExists( fn.GetFullPath() ) )
|
||||
return fn.GetFullPath();
|
||||
}
|
||||
|
||||
fn = fullFileName;
|
||||
wxString name = Kiface().KifaceSearch().FindValidPath( fn.GetFullName() );
|
||||
|
||||
if( !name.IsEmpty() )
|
||||
fullFileName = name;
|
||||
|
||||
return fullFileName;
|
||||
}
|
||||
|
@ -276,6 +276,9 @@ const char* DSNLEXER::Syntax( int aTok )
|
||||
case DSN_EOF:
|
||||
ret = "end of input";
|
||||
break;
|
||||
case DSN_BAR:
|
||||
ret = "|";
|
||||
break;
|
||||
default:
|
||||
ret = "???";
|
||||
}
|
||||
@ -379,6 +382,15 @@ void DSNLEXER::NeedRIGHT()
|
||||
}
|
||||
|
||||
|
||||
void DSNLEXER::NeedBAR()
|
||||
{
|
||||
int tok = NextTok();
|
||||
|
||||
if( tok != DSN_BAR )
|
||||
Expecting( DSN_BAR );
|
||||
}
|
||||
|
||||
|
||||
int DSNLEXER::NeedSYMBOL()
|
||||
{
|
||||
int tok = NextTok();
|
||||
@ -452,7 +464,7 @@ inline bool isDigit( char cc )
|
||||
///< @return true if @a cc is an s-expression separator character.
|
||||
inline bool isSep( char cc )
|
||||
{
|
||||
return isSpace( cc ) || cc=='(' || cc==')';
|
||||
return isSpace( cc ) || cc == '(' || cc == ')' || cc == '|';
|
||||
}
|
||||
|
||||
|
||||
@ -597,6 +609,14 @@ L_read:
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if( *cur == '|' )
|
||||
{
|
||||
curText = *cur;
|
||||
curTok = DSN_BAR;
|
||||
head = cur+1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// Non-specctraMode, understands and deciphers escaped \, \r, \n, and \".
|
||||
// Strips off leading and trailing double quotes
|
||||
if( !specctraMode )
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <pgm_base.h>
|
||||
#include <common.h>
|
||||
#include <confirm.h>
|
||||
#include <embedded_files.h>
|
||||
#include <gestfich.h>
|
||||
#include <settings/common_settings.h>
|
||||
|
||||
@ -58,7 +59,8 @@ static const wxFileTypeInfo EDAfallbacks[] =
|
||||
};
|
||||
|
||||
|
||||
bool GetAssociatedDocument( wxWindow* aParent, const wxString& aDocName, PROJECT* aProject, SEARCH_STACK* aPaths )
|
||||
bool GetAssociatedDocument( wxWindow* aParent, const wxString& aDocName, PROJECT* aProject,
|
||||
SEARCH_STACK* aPaths, EMBEDDED_FILES* aFiles )
|
||||
{
|
||||
wxString docname;
|
||||
wxString fullfilename;
|
||||
@ -74,8 +76,48 @@ bool GetAssociatedDocument( wxWindow* aParent, const wxString& aDocName, PROJECT
|
||||
wxURI uri( docname );
|
||||
wxLogNull logNo; // Disable log messages
|
||||
|
||||
if( uri.HasScheme() && wxLaunchDefaultBrowser( docname ) )
|
||||
return true;
|
||||
if( uri.HasScheme() )
|
||||
{
|
||||
wxString scheme = uri.GetScheme().Lower();
|
||||
|
||||
if( scheme != FILEEXT::KiCadUriPrefix )
|
||||
{
|
||||
if( wxLaunchDefaultBrowser( docname ) )
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !aFiles )
|
||||
{
|
||||
wxLogTrace( wxT( "KICAD_EMBED" ),
|
||||
wxT( "No EMBEDDED_FILES object provided for kicad_embed URI" ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !docname.starts_with( FILEEXT::KiCadUriPrefix + "://" ) )
|
||||
{
|
||||
wxLogTrace( wxT( "KICAD_EMBED" ),
|
||||
wxT( "Invalid kicad_embed URI '%s'" ), docname );
|
||||
return false;
|
||||
}
|
||||
|
||||
docname = docname.Mid( 14 );
|
||||
|
||||
wxFileName temp_file = aFiles->GetTempFileName( docname );
|
||||
|
||||
if( !temp_file.IsOk() )
|
||||
{
|
||||
wxLogTrace( wxT( "KICAD_EMBED" ),
|
||||
wxT( "Failed to get temp file '%s' for kicad_embed URI" ), docname );
|
||||
return false;
|
||||
}
|
||||
|
||||
wxLogTrace( wxT( "KICAD_EMBED" ),
|
||||
wxT( "Opening embedded file '%s' as '%s'" ),
|
||||
docname, temp_file.GetFullPath() );
|
||||
docname = temp_file.GetFullPath();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
|
511
common/embedded_files.cpp
Normal file
511
common/embedded_files.cpp
Normal file
@ -0,0 +1,511 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 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/>.
|
||||
*/
|
||||
|
||||
#include <wx/base64.h>
|
||||
#include <wx/debug.h>
|
||||
#include <wx/file.h>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/mstream.h>
|
||||
#include <wx/wfstream.h>
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
#include <zstd.h>
|
||||
|
||||
#include <embedded_files.h>
|
||||
#include <kiid.h>
|
||||
#include <paths.h>
|
||||
|
||||
|
||||
|
||||
EMBEDDED_FILES::EMBEDDED_FILE* EMBEDDED_FILES::AddFile( const wxFileName& aName, bool aOverwrite )
|
||||
{
|
||||
if( HasFile( aName.GetFullName() ) )
|
||||
{
|
||||
if( !aOverwrite )
|
||||
return m_files[aName.GetFullName()];
|
||||
|
||||
m_files.erase( aName.GetFullName() );
|
||||
}
|
||||
|
||||
wxFFileInputStream file( aName.GetFullPath() );
|
||||
wxMemoryBuffer buffer;
|
||||
|
||||
if( !file.IsOk() )
|
||||
return nullptr;
|
||||
|
||||
wxFileOffset length = file.GetLength();
|
||||
|
||||
std::unique_ptr<EMBEDDED_FILE> efile = std::make_unique<EMBEDDED_FILE>();
|
||||
efile->name = aName.GetFullName();
|
||||
efile->decompressedData.resize( length );
|
||||
|
||||
wxString ext = aName.GetExt().Upper();
|
||||
|
||||
// Handle some common file extensions
|
||||
if( ext == "STP" || ext == "STPZ" || ext == "STEP" || ext == "WRL" || ext == "WRZ" )
|
||||
{
|
||||
efile->type = EMBEDDED_FILE::FILE_TYPE::MODEL;
|
||||
}
|
||||
else if( ext == "WOFF" || ext == "WOFF2" || ext == "TTF" || ext == "OTF" )
|
||||
{
|
||||
efile->type = EMBEDDED_FILE::FILE_TYPE::FONT;
|
||||
}
|
||||
else if( ext == "PDF" )
|
||||
{
|
||||
efile->type = EMBEDDED_FILE::FILE_TYPE::DATASHEET;
|
||||
}
|
||||
else if( ext == "KICAD_WKS" )
|
||||
{
|
||||
efile->type = EMBEDDED_FILE::FILE_TYPE::WORKSHEET;
|
||||
}
|
||||
|
||||
if( !efile->decompressedData.data() )
|
||||
return nullptr;
|
||||
|
||||
char* data = efile->decompressedData.data();
|
||||
wxFileOffset total_read = 0;
|
||||
|
||||
while( !file.Eof() && total_read < length )
|
||||
{
|
||||
file.Read( data, length - total_read );
|
||||
|
||||
size_t read = file.LastRead();
|
||||
data += read;
|
||||
total_read += read;
|
||||
}
|
||||
|
||||
if( CompressAndEncode( *efile ) != RETURN_CODE::OK )
|
||||
return nullptr;
|
||||
|
||||
efile->is_valid = true;
|
||||
|
||||
m_files[aName.GetFullName()] = efile.release();
|
||||
|
||||
return m_files[aName.GetFullName()];
|
||||
}
|
||||
|
||||
|
||||
void EMBEDDED_FILES::AddFile( EMBEDDED_FILE* aFile )
|
||||
{
|
||||
m_files.insert( { aFile->name, aFile } );
|
||||
}
|
||||
|
||||
// Remove a file from the collection
|
||||
void EMBEDDED_FILES::RemoveFile( const wxString& name, bool aErase )
|
||||
{
|
||||
auto it = m_files.find( name );
|
||||
|
||||
if( it != m_files.end() )
|
||||
{
|
||||
m_files.erase( it );
|
||||
|
||||
if( aErase )
|
||||
delete it->second;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EMBEDDED_FILES::ClearEmbeddedFonts()
|
||||
{
|
||||
for( auto it = m_files.begin(); it != m_files.end(); )
|
||||
{
|
||||
if( it->second->type == EMBEDDED_FILE::FILE_TYPE::FONT )
|
||||
{
|
||||
delete it->second;
|
||||
it = m_files.erase( it );
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Write the collection of files to a disk file in the specified format
|
||||
void EMBEDDED_FILES::WriteEmbeddedFiles( OUTPUTFORMATTER& aOut, int aNestLevel,
|
||||
bool aWriteData ) const
|
||||
{
|
||||
ssize_t MIME_BASE64_LENGTH = 76;
|
||||
aOut.Print( aNestLevel, "(embedded_files\n" );
|
||||
|
||||
for( const auto& [name, entry] : m_files )
|
||||
{
|
||||
const EMBEDDED_FILE& file = *entry;
|
||||
|
||||
aOut.Print( aNestLevel + 1, "(file\n" );
|
||||
aOut.Print( aNestLevel + 2, "(name \"%s\")\n", file.name.c_str().AsChar() );
|
||||
|
||||
const char* type = nullptr;
|
||||
|
||||
switch( file.type )
|
||||
{
|
||||
case EMBEDDED_FILE::FILE_TYPE::DATASHEET:
|
||||
type = "datasheet";
|
||||
break;
|
||||
case EMBEDDED_FILE::FILE_TYPE::FONT:
|
||||
type = "font";
|
||||
break;
|
||||
case EMBEDDED_FILE::FILE_TYPE::MODEL:
|
||||
type = "model";
|
||||
break;
|
||||
case EMBEDDED_FILE::FILE_TYPE::WORKSHEET:
|
||||
type = "worksheet";
|
||||
break;
|
||||
default:
|
||||
type = "other";
|
||||
break;
|
||||
}
|
||||
|
||||
aOut.Print( aNestLevel + 2, "(type %s)\n", type );
|
||||
|
||||
if( aWriteData )
|
||||
{
|
||||
aOut.Print( 2, "(data\n" );
|
||||
|
||||
size_t first = 0;
|
||||
|
||||
while( first < file.compressedEncodedData.length() )
|
||||
{
|
||||
ssize_t remaining = file.compressedEncodedData.length() - first;
|
||||
int length = std::min( remaining, MIME_BASE64_LENGTH );
|
||||
|
||||
std::string_view view( file.compressedEncodedData.data() + first, length );
|
||||
|
||||
aOut.Print( aNestLevel + 3, "%1s%.*s%s\n", first ? "" : "|", length, view.data(),
|
||||
remaining == length ? "|" : "" );
|
||||
first += MIME_BASE64_LENGTH;
|
||||
}
|
||||
aOut.Print( aNestLevel + 2, ")\n" ); // Close data
|
||||
}
|
||||
|
||||
aOut.Print( aNestLevel + 2, "(checksum \"%s\")\n", file.data_sha.c_str() );
|
||||
aOut.Print( aNestLevel + 1, ")\n" ); // Close file
|
||||
}
|
||||
|
||||
aOut.Print( aNestLevel, ")\n" ); // Close embedded_files
|
||||
}
|
||||
|
||||
// Compress and Base64 encode data
|
||||
EMBEDDED_FILES::RETURN_CODE EMBEDDED_FILES::CompressAndEncode( EMBEDDED_FILE& aFile )
|
||||
{
|
||||
std::vector<char> compressedData;
|
||||
size_t estCompressedSize = ZSTD_compressBound( aFile.decompressedData.size() );
|
||||
compressedData.resize( estCompressedSize );
|
||||
size_t compressedSize = ZSTD_compress( compressedData.data(), estCompressedSize,
|
||||
aFile.decompressedData.data(),
|
||||
aFile.decompressedData.size(), 15 );
|
||||
|
||||
if( ZSTD_isError( compressedSize ) )
|
||||
{
|
||||
compressedData.clear();
|
||||
return RETURN_CODE::OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
const size_t dstLen = wxBase64EncodedSize( compressedSize );
|
||||
aFile.compressedEncodedData.resize( dstLen );
|
||||
size_t retval = wxBase64Encode( aFile.compressedEncodedData.data(), dstLen,
|
||||
compressedData.data(), compressedSize );
|
||||
if( retval != dstLen )
|
||||
{
|
||||
aFile.compressedEncodedData.clear();
|
||||
return RETURN_CODE::OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
picosha2::hash256_hex_string( aFile.decompressedData, aFile.data_sha );
|
||||
|
||||
return RETURN_CODE::OK;
|
||||
}
|
||||
|
||||
// Decompress and Base64 decode data
|
||||
EMBEDDED_FILES::RETURN_CODE EMBEDDED_FILES::DecompressAndDecode( EMBEDDED_FILE& aFile )
|
||||
{
|
||||
std::vector<char> compressedData;
|
||||
size_t compressedSize = wxBase64DecodedSize( aFile.compressedEncodedData.size() );
|
||||
|
||||
if( compressedSize == 0 )
|
||||
{
|
||||
wxLogTrace( wxT( "KICAD_EMBED" ),
|
||||
wxT( "%s:%s:%d\n * Base64DecodedSize failed for file '%s' with size %zu" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aFile.name, aFile.compressedEncodedData.size() );
|
||||
return RETURN_CODE::OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
compressedData.resize( compressedSize );
|
||||
void* compressed = compressedData.data();
|
||||
|
||||
// The return value from wxBase64Decode is the actual size of the decoded data avoiding
|
||||
// the modulo 4 padding of the base64 encoding
|
||||
compressedSize = wxBase64Decode( compressed, compressedSize, aFile.compressedEncodedData );
|
||||
|
||||
unsigned long long estDecompressedSize = ZSTD_getFrameContentSize( compressed, compressedSize );
|
||||
|
||||
if( estDecompressedSize > 1e9 ) // Limit to 1GB
|
||||
return RETURN_CODE::OUT_OF_MEMORY;
|
||||
|
||||
if( estDecompressedSize == ZSTD_CONTENTSIZE_ERROR
|
||||
|| estDecompressedSize == ZSTD_CONTENTSIZE_UNKNOWN )
|
||||
{
|
||||
return RETURN_CODE::OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
aFile.decompressedData.resize( estDecompressedSize );
|
||||
void* decompressed = aFile.decompressedData.data();
|
||||
|
||||
size_t decompressedSize = ZSTD_decompress( decompressed, estDecompressedSize,
|
||||
compressed, compressedSize );
|
||||
|
||||
if( ZSTD_isError( decompressedSize ) )
|
||||
{
|
||||
wxLogTrace( wxT( "KICAD_EMBED" ),
|
||||
wxT( "%s:%s:%d\n * ZSTD_decompress failed with error '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, ZSTD_getErrorName( decompressedSize ) );
|
||||
aFile.decompressedData.clear();
|
||||
return RETURN_CODE::OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
aFile.decompressedData.resize( decompressedSize );
|
||||
|
||||
std::string new_sha;
|
||||
picosha2::hash256_hex_string( aFile.decompressedData, new_sha );
|
||||
|
||||
if( new_sha != aFile.data_sha )
|
||||
{
|
||||
wxLogTrace( wxT( "KICAD_EMBED" ),
|
||||
wxT( "%s:%s:%d\n * Checksum error in embedded file '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aFile.name );
|
||||
aFile.decompressedData.clear();
|
||||
return RETURN_CODE::CHECKSUM_ERROR;
|
||||
}
|
||||
|
||||
return RETURN_CODE::OK;
|
||||
}
|
||||
|
||||
// Parsing method
|
||||
void EMBEDDED_FILES_PARSER::ParseEmbedded( EMBEDDED_FILES* aFiles )
|
||||
{
|
||||
if( !aFiles )
|
||||
THROW_PARSE_ERROR( "No embedded files object provided", CurSource(), CurLine(),
|
||||
CurLineNumber(), CurOffset() );
|
||||
|
||||
using namespace EMBEDDED_FILES_T;
|
||||
|
||||
std::unique_ptr<EMBEDDED_FILES::EMBEDDED_FILE> file( nullptr );
|
||||
|
||||
for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
|
||||
{
|
||||
if( token != T_LEFT )
|
||||
Expecting( T_LEFT );
|
||||
|
||||
token = NextTok();
|
||||
|
||||
if( token != T_file )
|
||||
Expecting( "file" );
|
||||
|
||||
if( file )
|
||||
{
|
||||
if( !file->compressedEncodedData.empty() )
|
||||
{
|
||||
EMBEDDED_FILES::DecompressAndDecode( *file );
|
||||
|
||||
if( !file->Validate() )
|
||||
THROW_PARSE_ERROR( "Checksum error in embedded file " + file->name, CurSource(),
|
||||
CurLine(), CurLineNumber(), CurOffset() );
|
||||
}
|
||||
|
||||
aFiles->AddFile( file.release() );
|
||||
}
|
||||
|
||||
file = std::unique_ptr<EMBEDDED_FILES::EMBEDDED_FILE>( nullptr );
|
||||
|
||||
|
||||
for( token = NextTok(); token != T_RIGHT; token = NextTok() )
|
||||
{
|
||||
if( token != T_LEFT )
|
||||
Expecting( T_LEFT );
|
||||
|
||||
token = NextTok();
|
||||
|
||||
switch( token )
|
||||
{
|
||||
|
||||
case T_checksum:
|
||||
NeedSYMBOLorNUMBER();
|
||||
|
||||
if( !IsSymbol( token ) )
|
||||
Expecting( "checksum data" );
|
||||
|
||||
file->data_sha = CurStr();
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_data:
|
||||
NeedBAR();
|
||||
token = NextTok();
|
||||
|
||||
file->compressedEncodedData.reserve( 1 << 17 );
|
||||
|
||||
while( token != T_BAR )
|
||||
{
|
||||
if( !IsSymbol( token ) )
|
||||
Expecting( "base64 file data" );
|
||||
|
||||
file->compressedEncodedData += CurStr();
|
||||
token = NextTok();
|
||||
}
|
||||
|
||||
file->compressedEncodedData.shrink_to_fit();
|
||||
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_name:
|
||||
|
||||
if( file )
|
||||
{
|
||||
wxLogTrace( wxT( "KICAD_EMBED" ),
|
||||
wxT( "Duplicate 'name' tag in embedded file %s" ), file->name );
|
||||
}
|
||||
|
||||
NeedSYMBOLorNUMBER();
|
||||
|
||||
file = std::make_unique<EMBEDDED_FILES::EMBEDDED_FILE>();
|
||||
file->name = CurStr();
|
||||
NeedRIGHT();
|
||||
|
||||
break;
|
||||
|
||||
case T_type:
|
||||
|
||||
token = NextTok();
|
||||
|
||||
switch( token )
|
||||
{
|
||||
case T_datasheet:
|
||||
file->type = EMBEDDED_FILES::EMBEDDED_FILE::FILE_TYPE::DATASHEET;
|
||||
break;
|
||||
case T_font:
|
||||
file->type = EMBEDDED_FILES::EMBEDDED_FILE::FILE_TYPE::FONT;
|
||||
break;
|
||||
case T_model:
|
||||
file->type = EMBEDDED_FILES::EMBEDDED_FILE::FILE_TYPE::MODEL;
|
||||
break;
|
||||
case T_worksheet:
|
||||
file->type = EMBEDDED_FILES::EMBEDDED_FILE::FILE_TYPE::WORKSHEET;
|
||||
break;
|
||||
case T_other:
|
||||
file->type = EMBEDDED_FILES::EMBEDDED_FILE::FILE_TYPE::OTHER;
|
||||
break;
|
||||
default:
|
||||
Expecting( "datasheet, font, model, worksheet or other" );
|
||||
break;
|
||||
}
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
default:
|
||||
Expecting( "checksum, data or name" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the last file in the collection
|
||||
if( file )
|
||||
{
|
||||
if( !file->compressedEncodedData.empty() )
|
||||
{
|
||||
EMBEDDED_FILES::DecompressAndDecode( *file );
|
||||
|
||||
if( !file->Validate() )
|
||||
THROW_PARSE_ERROR( "Checksum error in embedded file " + file->name, CurSource(),
|
||||
CurLine(), CurLineNumber(), CurOffset() );
|
||||
}
|
||||
|
||||
aFiles->AddFile( file.release() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
wxFileName EMBEDDED_FILES::GetTempFileName( const wxString& aName ) const
|
||||
{
|
||||
wxFileName cacheFile;
|
||||
|
||||
auto it = m_files.find( aName );
|
||||
|
||||
if( it == m_files.end() )
|
||||
return cacheFile;
|
||||
|
||||
cacheFile.AssignDir( PATHS::GetUserCachePath() );
|
||||
cacheFile.AppendDir( wxT( "embed" ) );
|
||||
|
||||
if( !PATHS::EnsurePathExists( cacheFile.GetFullPath() ) )
|
||||
{
|
||||
wxLogTrace( wxT( "KICAD_EMBED" ),
|
||||
wxT( "%s:%s:%d\n * failed to create embed cache directory '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, cacheFile.GetPath() );
|
||||
|
||||
cacheFile.SetPath( wxFileName::GetTempDir() );
|
||||
}
|
||||
|
||||
wxFileName inputName( aName );
|
||||
|
||||
// Store the cache file name using the data SHA to allow for shared data between
|
||||
// multiple projects using the same files as well as deconflicting files with the same name
|
||||
cacheFile.SetName( "kicad_embedded_" + it->second->data_sha );
|
||||
cacheFile.SetExt( inputName.GetExt() );
|
||||
|
||||
if( cacheFile.FileExists() && cacheFile.IsFileReadable() )
|
||||
return cacheFile;
|
||||
|
||||
wxFFileOutputStream out( cacheFile.GetFullPath() );
|
||||
|
||||
if( !out.IsOk() )
|
||||
{
|
||||
cacheFile.Clear();
|
||||
return cacheFile;
|
||||
}
|
||||
|
||||
out.Write( it->second->decompressedData.data(), it->second->decompressedData.size() );
|
||||
|
||||
return cacheFile;
|
||||
}
|
||||
|
||||
|
||||
const std::vector<wxString>* EMBEDDED_FILES::GetFontFiles() const
|
||||
{
|
||||
return &m_fontFiles;
|
||||
}
|
||||
|
||||
|
||||
const std::vector<wxString>* EMBEDDED_FILES::UpdateFontFiles()
|
||||
{
|
||||
m_fontFiles.clear();
|
||||
|
||||
for( const auto& [name, entry] : m_files )
|
||||
{
|
||||
if( entry->type == EMBEDDED_FILE::FILE_TYPE::FONT )
|
||||
m_fontFiles.push_back( GetTempFileName( name ).GetFullPath() );
|
||||
}
|
||||
|
||||
return &m_fontFiles;
|
||||
}
|
13
common/embedded_files.keywords
Normal file
13
common/embedded_files.keywords
Normal file
@ -0,0 +1,13 @@
|
||||
checksum
|
||||
data
|
||||
datasheet
|
||||
embedded_files
|
||||
embedded_fonts
|
||||
file
|
||||
font
|
||||
model
|
||||
name
|
||||
other
|
||||
reference
|
||||
type
|
||||
worksheet
|
@ -27,10 +27,12 @@
|
||||
#include <sstream>
|
||||
|
||||
#include <wx/log.h>
|
||||
#include <wx/uri.h>
|
||||
#include <pgm_base.h>
|
||||
#include <trace_helpers.h>
|
||||
|
||||
#include <common.h>
|
||||
#include <embedded_files.h>
|
||||
#include <env_vars.h>
|
||||
#include <filename_resolver.h>
|
||||
#include <confirm.h>
|
||||
@ -241,7 +243,8 @@ bool FILENAME_RESOLVER::UpdatePathList( const std::vector< SEARCH_PATH >& aPathL
|
||||
}
|
||||
|
||||
|
||||
wxString FILENAME_RESOLVER::ResolvePath( const wxString& aFileName, const wxString& aWorkingPath )
|
||||
wxString FILENAME_RESOLVER::ResolvePath( const wxString& aFileName, const wxString& aWorkingPath,
|
||||
const EMBEDDED_FILES* aFiles )
|
||||
{
|
||||
std::lock_guard<std::mutex> lock( mutex_resolver );
|
||||
|
||||
@ -260,6 +263,32 @@ wxString FILENAME_RESOLVER::ResolvePath( const wxString& aFileName, const wxStri
|
||||
// for getenv().
|
||||
tname = ExpandEnvVarSubstitutions( tname, m_project );
|
||||
|
||||
// Check to see if the file is a URI for an embedded file.
|
||||
if( tname.StartsWith( FILEEXT::KiCadUriPrefix + "://" ) )
|
||||
{
|
||||
if( !aFiles )
|
||||
{
|
||||
wxLogTrace( wxT( "KICAD_EMBED" ),
|
||||
wxT( "No EMBEDDED_FILES object provided for kicad_embed URI" ) );
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
wxString path = tname.Mid( 14 );
|
||||
wxFileName temp_file = aFiles->GetTempFileName( path );
|
||||
|
||||
if( !temp_file.IsOk() )
|
||||
{
|
||||
wxLogTrace( wxT( "KICAD_EMBED" ),
|
||||
wxT( "Failed to get temp file '%s' for kicad_embed URI" ), path );
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
wxLogTrace( wxT( "KICAD_EMBED" ), wxT( "Opening embedded file '%s' as '%s'" ),
|
||||
tname, temp_file.GetFullPath() );
|
||||
|
||||
return temp_file.GetFullPath();
|
||||
}
|
||||
|
||||
wxFileName tmpFN( tname );
|
||||
|
||||
// this case covers full paths, leading expanded vars, and paths relative to the current
|
||||
@ -688,11 +717,23 @@ bool FILENAME_RESOLVER::ValidateFileName( const wxString& aFileName, bool& hasAl
|
||||
// ALIAS:relative/path
|
||||
// 2. ALIAS is a UTF string excluding wxT( "{}[]()%~<>\"='`;:.,&?/\\|$" )
|
||||
// 3. The relative path must be a valid relative path for the platform
|
||||
// 4. We allow a URI for embedded files, but only if it has a name
|
||||
|
||||
hasAlias = false;
|
||||
|
||||
if( aFileName.empty() )
|
||||
return false;
|
||||
|
||||
if( aFileName.StartsWith( wxT( "file://" ) )
|
||||
|| aFileName.StartsWith( FILEEXT::KiCadUriPrefix + "://" ) )
|
||||
{
|
||||
size_t prefixLength = aFileName.StartsWith( wxT( "file://" ) ) ? 7 : 14;
|
||||
if( aFileName.length() > prefixLength && aFileName[prefixLength] != '/' )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
wxString filename = aFileName;
|
||||
wxString lpath;
|
||||
size_t aliasStart = aFileName.StartsWith( ':' ) ? 1 : 0;
|
||||
|
@ -143,7 +143,7 @@ FONT* FONT::getDefaultFont()
|
||||
}
|
||||
|
||||
|
||||
FONT* FONT::GetFont( const wxString& aFontName, bool aBold, bool aItalic )
|
||||
FONT* FONT::GetFont( const wxString& aFontName, bool aBold, bool aItalic, const std::vector<wxString>* aEmbeddedFiles )
|
||||
{
|
||||
if( aFontName.empty() || aFontName.StartsWith( KICAD_FONT_NAME ) )
|
||||
return getDefaultFont();
|
||||
@ -156,7 +156,7 @@ FONT* FONT::GetFont( const wxString& aFontName, bool aBold, bool aItalic )
|
||||
font = s_fontMap[key];
|
||||
|
||||
if( !font )
|
||||
font = OUTLINE_FONT::LoadFont( aFontName, aBold, aItalic );
|
||||
font = OUTLINE_FONT::LoadFont( aFontName, aBold, aItalic, aEmbeddedFiles );
|
||||
|
||||
if( !font )
|
||||
font = getDefaultFont();
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <macros.h>
|
||||
#include <cstdint>
|
||||
#include <reporter.h>
|
||||
#include <embedded_files.h>
|
||||
|
||||
#ifdef __WIN32__
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
@ -196,14 +197,25 @@ std::string FONTCONFIG::getFamilyStringByLang( FONTCONFIG_PAT& aPat, const wxStr
|
||||
}
|
||||
|
||||
|
||||
FONTCONFIG::FF_RESULT FONTCONFIG::FindFont( const wxString &aFontName, wxString &aFontFile,
|
||||
int& aFaceIndex, bool aBold, bool aItalic )
|
||||
FONTCONFIG::FF_RESULT FONTCONFIG::FindFont( const wxString& aFontName, wxString& aFontFile,
|
||||
int& aFaceIndex, bool aBold, bool aItalic,
|
||||
const std::vector<wxString>* aEmbeddedFiles )
|
||||
{
|
||||
FF_RESULT retval = FF_RESULT::FF_ERROR;
|
||||
|
||||
if( !g_fcInitSuccess )
|
||||
return retval;
|
||||
|
||||
FcConfig* config = FcConfigGetCurrent();
|
||||
|
||||
if( aEmbeddedFiles )
|
||||
{
|
||||
for( const auto& file : *aEmbeddedFiles )
|
||||
{
|
||||
FcConfigAppFontAddFile( config, (const FcChar8*) file.c_str().AsChar() );
|
||||
}
|
||||
}
|
||||
|
||||
wxString qualifiedFontName = aFontName;
|
||||
|
||||
wxScopedCharBuffer const fcBuffer = qualifiedFontName.ToUTF8();
|
||||
@ -218,11 +230,11 @@ FONTCONFIG::FF_RESULT FONTCONFIG::FindFont( const wxString &aFontName, wxString
|
||||
|
||||
FcPatternAddString( pat, FC_FAMILY, (FcChar8*) fcBuffer.data() );
|
||||
|
||||
FcConfigSubstitute( nullptr, pat, FcMatchPattern );
|
||||
FcConfigSubstitute( config, pat, FcMatchPattern );
|
||||
FcDefaultSubstitute( pat );
|
||||
|
||||
FcResult r = FcResultNoMatch;
|
||||
FcPattern* font = FcFontMatch( nullptr, pat, &r );
|
||||
FcPattern* font = FcFontMatch( config, pat, &r );
|
||||
|
||||
wxString fontName;
|
||||
|
||||
@ -342,18 +354,29 @@ FONTCONFIG::FF_RESULT FONTCONFIG::FindFont( const wxString &aFontName, wxString
|
||||
}
|
||||
|
||||
|
||||
void FONTCONFIG::ListFonts( std::vector<std::string>& aFonts, const std::string& aDesiredLang )
|
||||
void FONTCONFIG::ListFonts( std::vector<std::string>& aFonts, const std::string& aDesiredLang,
|
||||
const std::vector<wxString>* aEmbeddedFiles, bool aForce )
|
||||
{
|
||||
if( !g_fcInitSuccess )
|
||||
return;
|
||||
|
||||
// be sure to cache bust if the language changed
|
||||
if( m_fontInfoCache.empty() || m_fontCacheLastLang != aDesiredLang )
|
||||
if( m_fontInfoCache.empty() || m_fontCacheLastLang != aDesiredLang || aForce )
|
||||
{
|
||||
FcConfig* config = FcConfigGetCurrent();
|
||||
|
||||
if( aEmbeddedFiles )
|
||||
{
|
||||
for( const auto& file : *aEmbeddedFiles )
|
||||
{
|
||||
FcConfigAppFontAddFile( config, (const FcChar8*) file.c_str().AsChar() );
|
||||
}
|
||||
}
|
||||
|
||||
FcPattern* pat = FcPatternCreate();
|
||||
FcObjectSet* os = FcObjectSetBuild( FC_FAMILY, FC_FAMILYLANG, FC_STYLE, FC_LANG, FC_FILE,
|
||||
FC_OUTLINE, nullptr );
|
||||
FcFontSet* fs = FcFontList( nullptr, pat, os );
|
||||
FcFontSet* fs = FcFontList( config, pat, os );
|
||||
|
||||
for( int i = 0; fs && i < fs->nfont; ++i )
|
||||
{
|
||||
|
@ -29,6 +29,10 @@
|
||||
#include <geometry/shape_poly_set.h>
|
||||
#include <font/fontconfig.h>
|
||||
#include <font/outline_font.h>
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_SFNT_NAMES_H
|
||||
#include FT_TRUETYPE_TABLES_H
|
||||
#include FT_GLYPH_H
|
||||
#include FT_BBOX_H
|
||||
#include <trigo.h>
|
||||
@ -53,7 +57,33 @@ OUTLINE_FONT::OUTLINE_FONT() :
|
||||
}
|
||||
|
||||
|
||||
OUTLINE_FONT* OUTLINE_FONT::LoadFont( const wxString& aFontName, bool aBold, bool aItalic )
|
||||
OUTLINE_FONT::EMBEDDING_PERMISSION OUTLINE_FONT::GetEmbeddingPermission() const
|
||||
{
|
||||
TT_OS2* os2 = reinterpret_cast<TT_OS2*>( FT_Get_Sfnt_Table( m_face, FT_SFNT_OS2 ) );
|
||||
|
||||
// If this table isn't present, we can't assume anything
|
||||
if( !os2 )
|
||||
return EMBEDDING_PERMISSION::RESTRICTED;
|
||||
|
||||
if( os2->fsType == FT_FSTYPE_INSTALLABLE_EMBEDDING ) // This allows the font to be exported from KiCad
|
||||
return EMBEDDING_PERMISSION::INSTALLABLE;
|
||||
|
||||
if( os2->fsType & FT_FSTYPE_BITMAP_EMBEDDING_ONLY ) // We don't support bitmap fonts, so this disables embedding
|
||||
return EMBEDDING_PERMISSION::RESTRICTED;
|
||||
|
||||
if( os2->fsType & FT_FSTYPE_EDITABLE_EMBEDDING ) // This allows us to use the font in KiCad but not export
|
||||
return EMBEDDING_PERMISSION::EDITABLE;
|
||||
|
||||
if( os2->fsType & FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING ) // This is not actually supported by KiCad ATM(2024)
|
||||
return EMBEDDING_PERMISSION::PRINT_PREVIEW_ONLY;
|
||||
|
||||
// Anything else that is not explicitly enabled we treat as restricted.
|
||||
return EMBEDDING_PERMISSION::RESTRICTED;
|
||||
}
|
||||
|
||||
|
||||
OUTLINE_FONT* OUTLINE_FONT::LoadFont( const wxString& aFontName, bool aBold, bool aItalic,
|
||||
const std::vector<wxString>* aEmbeddedFiles )
|
||||
{
|
||||
std::unique_ptr<OUTLINE_FONT> font = std::make_unique<OUTLINE_FONT>();
|
||||
|
||||
@ -61,7 +91,9 @@ OUTLINE_FONT* OUTLINE_FONT::LoadFont( const wxString& aFontName, bool aBold, boo
|
||||
int faceIndex;
|
||||
using fc = fontconfig::FONTCONFIG;
|
||||
|
||||
fc::FF_RESULT retval = Fontconfig()->FindFont( aFontName, fontFile, faceIndex, aBold, aItalic );
|
||||
|
||||
fc::FF_RESULT retval = Fontconfig()->FindFont( aFontName, fontFile, faceIndex, aBold, aItalic,
|
||||
aEmbeddedFiles );
|
||||
|
||||
if( retval == fc::FF_RESULT::FF_ERROR )
|
||||
return nullptr;
|
||||
|
@ -149,30 +149,6 @@ ALTIUM_COMPOUND_FILE::DecodeIntLibStream( const CFB::COMPOUND_FILE_ENTRY& cfe )
|
||||
}
|
||||
|
||||
|
||||
std::map<wxString, wxString> ALTIUM_COMPOUND_FILE::ListLibFootprints()
|
||||
{
|
||||
if( m_libFootprintDirNameCache.empty() )
|
||||
cacheLibFootprintNames();
|
||||
|
||||
return m_libFootprintDirNameCache;
|
||||
}
|
||||
|
||||
|
||||
std::tuple<wxString, const CFB::COMPOUND_FILE_ENTRY*>
|
||||
ALTIUM_COMPOUND_FILE::FindLibFootprintDirName( const wxString& aFpUnicodeName )
|
||||
{
|
||||
if( m_libFootprintNameCache.empty() )
|
||||
cacheLibFootprintNames();
|
||||
|
||||
auto it = m_libFootprintNameCache.find( aFpUnicodeName );
|
||||
|
||||
if( it == m_libFootprintNameCache.end() )
|
||||
return { wxEmptyString, nullptr };
|
||||
|
||||
return { it->first, it->second };
|
||||
}
|
||||
|
||||
|
||||
const CFB::COMPOUND_FILE_ENTRY*
|
||||
ALTIUM_COMPOUND_FILE::FindStreamSingleLevel( const CFB::COMPOUND_FILE_ENTRY* aEntry,
|
||||
const std::string aName, const bool aIsStream ) const
|
||||
@ -333,53 +309,6 @@ ALTIUM_COMPOUND_FILE::FindStream( const std::vector<std::string>& aStreamPath )
|
||||
}
|
||||
|
||||
|
||||
void ALTIUM_COMPOUND_FILE::cacheLibFootprintNames()
|
||||
{
|
||||
m_libFootprintDirNameCache.clear();
|
||||
m_libFootprintNameCache.clear();
|
||||
|
||||
if( !m_reader )
|
||||
return;
|
||||
|
||||
const CFB::COMPOUND_FILE_ENTRY* root = m_reader->GetRootEntry();
|
||||
|
||||
if( !root )
|
||||
return;
|
||||
|
||||
m_reader->EnumFiles( root, 1,
|
||||
[this]( const CFB::COMPOUND_FILE_ENTRY* tentry, const CFB::utf16string& dir,
|
||||
int level ) -> int
|
||||
{
|
||||
if( m_reader->IsStream( tentry ) )
|
||||
return 0;
|
||||
|
||||
m_reader->EnumFiles( tentry, 1,
|
||||
[&]( const CFB::COMPOUND_FILE_ENTRY* entry, const CFB::utf16string&, int ) -> int
|
||||
{
|
||||
std::wstring fileName = UTF16ToWstring( entry->name, entry->nameLen );
|
||||
|
||||
if( m_reader->IsStream( entry ) && fileName == L"Parameters" )
|
||||
{
|
||||
ALTIUM_BINARY_PARSER parametersReader( *this, entry );
|
||||
std::map<wxString, wxString> parameterProperties =
|
||||
parametersReader.ReadProperties();
|
||||
|
||||
wxString key = ALTIUM_PROPS_UTILS::ReadString(
|
||||
parameterProperties, wxT( "PATTERN" ), wxT( "" ) );
|
||||
wxString fpName = ALTIUM_PROPS_UTILS::ReadUnicodeString(
|
||||
parameterProperties, wxT( "PATTERN" ), wxT( "" ) );
|
||||
|
||||
m_libFootprintDirNameCache[key] = fpName;
|
||||
m_libFootprintNameCache[fpName] = tentry;
|
||||
}
|
||||
|
||||
return 0;
|
||||
} );
|
||||
return 0;
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
ALTIUM_BINARY_PARSER::ALTIUM_BINARY_PARSER( const ALTIUM_COMPOUND_FILE& aFile,
|
||||
const CFB::COMPOUND_FILE_ENTRY* aEntry )
|
||||
{
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <wx/mstream.h>
|
||||
#include <wx/zstream.h>
|
||||
#include <math/vector2d.h>
|
||||
#include <math/vector3.h>
|
||||
|
||||
namespace CFB
|
||||
{
|
||||
@ -63,8 +64,11 @@ public:
|
||||
const CFB::COMPOUND_FILE_ENTRY* m_pinsSymbolLineWidth;
|
||||
};
|
||||
|
||||
|
||||
class ALTIUM_COMPOUND_FILE
|
||||
{
|
||||
friend class ALTIUM_PCB_COMPOUND_FILE;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Open a CFB file. Constructor might throw an IO_ERROR.
|
||||
@ -90,10 +94,6 @@ public:
|
||||
|
||||
std::unique_ptr<ALTIUM_COMPOUND_FILE> DecodeIntLibStream( const CFB::COMPOUND_FILE_ENTRY& cfe );
|
||||
|
||||
std::map<wxString, wxString> ListLibFootprints();
|
||||
|
||||
std::tuple<wxString, const CFB::COMPOUND_FILE_ENTRY*> FindLibFootprintDirName( const wxString& aFpUnicodeName );
|
||||
|
||||
const CFB::COMPOUND_FILE_ENTRY* FindStream( const std::vector<std::string>& aStreamPath ) const;
|
||||
|
||||
const CFB::COMPOUND_FILE_ENTRY* FindStream( const CFB::COMPOUND_FILE_ENTRY* aStart, const std::vector<std::string>& aStreamPath ) const;
|
||||
@ -108,13 +108,8 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
void cacheLibFootprintNames();
|
||||
|
||||
std::unique_ptr<CFB::CompoundFileReader> m_reader;
|
||||
std::vector<char> m_buffer;
|
||||
|
||||
std::map<wxString, const CFB::COMPOUND_FILE_ENTRY*> m_libFootprintNameCache;
|
||||
std::map<wxString, wxString> m_libFootprintDirNameCache;
|
||||
};
|
||||
|
||||
|
||||
|
@ -106,6 +106,8 @@ edge_connector
|
||||
edge_plating
|
||||
edge_width
|
||||
effects
|
||||
embedded_fonts
|
||||
embedded_files
|
||||
enabled
|
||||
end
|
||||
epsilon_r
|
||||
|
@ -1184,6 +1184,26 @@ TOOL_ACTION ACTIONS::pluginsReload( TOOL_ACTION_ARGS()
|
||||
.Tooltip( _( "Reload all python plugins and refresh plugin menus" ) )
|
||||
.Icon( BITMAPS::reload ) );
|
||||
|
||||
// Embedding Files
|
||||
|
||||
TOOL_ACTION ACTIONS::embeddedFiles( TOOL_ACTION_ARGS()
|
||||
.Name( "common.Embed.embededFile" )
|
||||
.Scope( AS_GLOBAL )
|
||||
.FriendlyName( _( "Embedded Files" ) )
|
||||
.Tooltip( _( "Manage embedded files" ) ) );
|
||||
|
||||
TOOL_ACTION ACTIONS::removeFile( TOOL_ACTION_ARGS()
|
||||
.Name( "common.Embed.removeFile" )
|
||||
.Scope( AS_GLOBAL )
|
||||
.FriendlyName( _( "Remove File" ) )
|
||||
.Tooltip( _( "Remove an embedded file" ) ) );
|
||||
|
||||
TOOL_ACTION ACTIONS::extractFile( TOOL_ACTION_ARGS()
|
||||
.Name( "common.Embed.extractFile" )
|
||||
.Scope( AS_GLOBAL )
|
||||
.FriendlyName( _( "Extract File" ) )
|
||||
.Tooltip( _( "Extract an embedded file" ) ) );
|
||||
|
||||
// System-wide selection Events
|
||||
|
||||
const TOOL_EVENT EVENTS::PointSelectedEvent( TC_MESSAGE, TA_ACTION, "common.Interactive.pointSelected" );
|
||||
|
92
common/tool/embed_tool.cpp
Normal file
92
common/tool/embed_tool.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 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/>.
|
||||
*/
|
||||
|
||||
#include <dialogs/dialog_embed_files.h>
|
||||
#include <dialogs/panel_embedded_files.h>
|
||||
#include <eda_draw_frame.h>
|
||||
#include <eda_item.h>
|
||||
#include <embedded_files.h>
|
||||
#include <tool/actions.h>
|
||||
#include <wx/debug.h>
|
||||
#include <wx/filedlg.h>
|
||||
|
||||
#include <tool/embed_tool.h>
|
||||
|
||||
|
||||
EMBED_TOOL::EMBED_TOOL( const std::string& aName ) :
|
||||
TOOL_INTERACTIVE( aName )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
EMBED_TOOL::EMBED_TOOL() :
|
||||
TOOL_INTERACTIVE( "common.Embed" )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool EMBED_TOOL::Init()
|
||||
{
|
||||
|
||||
m_files = getModel<EDA_ITEM>()->GetEmbeddedFiles();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void EMBED_TOOL::Reset( RESET_REASON aReason )
|
||||
{
|
||||
m_files = getModel<EDA_ITEM>()->GetEmbeddedFiles();
|
||||
|
||||
}
|
||||
|
||||
int EMBED_TOOL::AddFile( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
wxString name = aEvent.Parameter<wxString>();
|
||||
m_files->AddFile( name, false );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EMBED_TOOL::RemoveFile( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
wxString name = aEvent.Parameter<wxString>();
|
||||
m_files->RemoveFile( name );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::vector<wxString> EMBED_TOOL::GetFileList()
|
||||
{
|
||||
std::vector<wxString> list;
|
||||
|
||||
for( auto& [name, file] : m_files->EmbeddedFileMap() )
|
||||
{
|
||||
list.push_back( name );
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void EMBED_TOOL::setTransitions()
|
||||
{
|
||||
Go( &EMBED_TOOL::AddFile, ACTIONS::embeddedFiles.MakeEvent() );
|
||||
Go( &EMBED_TOOL::RemoveFile, ACTIONS::removeFile.MakeEvent() );
|
||||
}
|
||||
|
@ -22,12 +22,14 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/combo.h>
|
||||
#include <wx/filedlg.h>
|
||||
#include <wx/dirdlg.h>
|
||||
#include <wx/textctrl.h>
|
||||
|
||||
#include <bitmaps.h>
|
||||
#include <embedded_files.h>
|
||||
#include <kiway.h>
|
||||
#include <kiway_player.h>
|
||||
#include <kiway_express.h>
|
||||
@ -37,6 +39,7 @@
|
||||
#include <env_paths.h>
|
||||
#include <pgm_base.h>
|
||||
#include <widgets/wx_grid.h>
|
||||
#include <widgets/filedlg_open_embed_file.h>
|
||||
#include <widgets/grid_text_button_helpers.h>
|
||||
#include <eda_doc.h>
|
||||
|
||||
@ -323,16 +326,25 @@ void GRID_CELL_FPID_EDITOR::Create( wxWindow* aParent, wxWindowID aId,
|
||||
class TEXT_BUTTON_URL : public wxComboCtrl
|
||||
{
|
||||
public:
|
||||
TEXT_BUTTON_URL( wxWindow* aParent, DIALOG_SHIM* aParentDlg, SEARCH_STACK* aSearchStack ) :
|
||||
TEXT_BUTTON_URL( wxWindow* aParent, DIALOG_SHIM* aParentDlg, SEARCH_STACK* aSearchStack, EMBEDDED_FILES* aFiles ) :
|
||||
wxComboCtrl( aParent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_PROCESS_ENTER | wxBORDER_NONE ),
|
||||
m_dlg( aParentDlg ),
|
||||
m_searchStack( aSearchStack )
|
||||
m_searchStack( aSearchStack ),
|
||||
m_files( aFiles )
|
||||
{
|
||||
SetButtonBitmaps( KiBitmapBundle( BITMAPS::www ) );
|
||||
UpdateButtonBitmaps();
|
||||
|
||||
// win32 fix, avoids drawing the "native dropdown caret"
|
||||
Customize( wxCC_IFLAG_HAS_NONSTANDARD_BUTTON );
|
||||
|
||||
// Bind event to handle text changes
|
||||
Bind(wxEVT_TEXT, &TEXT_BUTTON_URL::OnTextChange, this);
|
||||
}
|
||||
|
||||
~TEXT_BUTTON_URL()
|
||||
{
|
||||
Unbind(wxEVT_TEXT, &TEXT_BUTTON_URL::OnTextChange, this);
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -345,19 +357,59 @@ protected:
|
||||
{
|
||||
wxString filename = GetValue();
|
||||
|
||||
if( !filename.IsEmpty() && filename != wxT( "~" ) )
|
||||
GetAssociatedDocument( m_dlg, GetValue(), &m_dlg->Prj(), m_searchStack );
|
||||
if (filename.IsEmpty() || filename == wxT("~"))
|
||||
{
|
||||
FILEDLG_OPEN_EMBED_FILE customize;
|
||||
wxFileDialog openFileDialog( this, _( "Open file" ), "", "", "All files (*.*)|*.*",
|
||||
wxFD_OPEN | wxFD_FILE_MUST_EXIST );
|
||||
openFileDialog.SetCustomizeHook( customize );
|
||||
|
||||
if( openFileDialog.ShowModal() == wxID_OK )
|
||||
{
|
||||
filename = openFileDialog.GetPath();
|
||||
wxFileName fn( filename );
|
||||
|
||||
if( customize.GetEmbed() )
|
||||
{
|
||||
EMBEDDED_FILES::EMBEDDED_FILE* result = m_files->AddFile( fn, false );
|
||||
SetValue( result->GetLink() );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetValue( "file://" + filename );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GetAssociatedDocument(m_dlg, GetValue(), &m_dlg->Prj(), m_searchStack, m_files);
|
||||
}
|
||||
}
|
||||
|
||||
void OnTextChange(wxCommandEvent& event)
|
||||
{
|
||||
UpdateButtonBitmaps();
|
||||
event.Skip(); // Ensure that other handlers can process this event too
|
||||
}
|
||||
|
||||
void UpdateButtonBitmaps()
|
||||
{
|
||||
if (GetValue().IsEmpty())
|
||||
SetButtonBitmaps(KiBitmapBundle(BITMAPS::small_folder));
|
||||
else
|
||||
SetButtonBitmaps(KiBitmapBundle(BITMAPS::www));
|
||||
}
|
||||
|
||||
DIALOG_SHIM* m_dlg;
|
||||
SEARCH_STACK* m_searchStack;
|
||||
EMBEDDED_FILES* m_files;
|
||||
};
|
||||
|
||||
|
||||
void GRID_CELL_URL_EDITOR::Create( wxWindow* aParent, wxWindowID aId,
|
||||
wxEvtHandler* aEventHandler )
|
||||
{
|
||||
m_control = new TEXT_BUTTON_URL( aParent, m_dlg, m_searchStack );
|
||||
m_control = new TEXT_BUTTON_URL( aParent, m_dlg, m_searchStack, m_files );
|
||||
WX_GRID::CellEditorSetMargins( Combo() );
|
||||
|
||||
#if wxUSE_VALIDATORS
|
||||
|
@ -154,7 +154,7 @@ class WX_GRID_ALT_ROW_COLOR_PROVIDER : public wxGridCellAttrProvider
|
||||
{
|
||||
public:
|
||||
WX_GRID_ALT_ROW_COLOR_PROVIDER( const wxColor& aBaseColor ) : wxGridCellAttrProvider(),
|
||||
m_attrOdd( new wxGridCellAttr() )
|
||||
m_attrEven( new wxGridCellAttr() )
|
||||
{
|
||||
UpdateColors( aBaseColor );
|
||||
}
|
||||
@ -165,7 +165,7 @@ public:
|
||||
// Choose the default color, taking into account if the dark mode theme is enabled
|
||||
wxColor rowColor = aBaseColor.ChangeLightness( KIPLATFORM::UI::IsDarkTheme() ? 105 : 95 );
|
||||
|
||||
m_attrOdd->SetBackgroundColour( rowColor );
|
||||
m_attrEven->SetBackgroundColour( rowColor );
|
||||
}
|
||||
|
||||
|
||||
@ -174,20 +174,20 @@ public:
|
||||
{
|
||||
wxGridCellAttrPtr cellAttr( wxGridCellAttrProvider::GetAttr( row, col, kind ) );
|
||||
|
||||
// Just pass through the cell attribute on even rows
|
||||
if( row % 2 )
|
||||
// Just pass through the cell attribute on odd rows (start normal to allow for the header row)
|
||||
if( !( row % 2 ) )
|
||||
return cellAttr.release();
|
||||
|
||||
if( !cellAttr )
|
||||
{
|
||||
cellAttr = m_attrOdd;
|
||||
cellAttr = m_attrEven;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !cellAttr->HasBackgroundColour() )
|
||||
{
|
||||
cellAttr = cellAttr->Clone();
|
||||
cellAttr->SetBackgroundColour( m_attrOdd->GetBackgroundColour() );
|
||||
cellAttr->SetBackgroundColour( m_attrEven->GetBackgroundColour() );
|
||||
}
|
||||
}
|
||||
|
||||
@ -195,7 +195,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
wxGridCellAttrPtr m_attrOdd;
|
||||
wxGridCellAttrPtr m_attrEven;
|
||||
};
|
||||
|
||||
|
||||
|
@ -202,6 +202,8 @@ const std::string FILEEXT::XaoFileExtension( "xao" );
|
||||
|
||||
const wxString FILEEXT::GerberFileExtensionsRegex( "(gbr|gko|pho|(g[tb][alops])|(gm?\\d\\d*)|(gp[tb]))" );
|
||||
|
||||
const std::string FILEEXT::KiCadUriPrefix( "kicad-embed" );
|
||||
|
||||
|
||||
bool FILEEXT::IsGerberFileExtension( const wxString& ext )
|
||||
{
|
||||
|
@ -26,9 +26,9 @@
|
||||
#include <schematic.h>
|
||||
#include <eeschema_settings.h>
|
||||
|
||||
DIALOG_EESCHEMA_PAGE_SETTINGS::DIALOG_EESCHEMA_PAGE_SETTINGS( EDA_DRAW_FRAME* aParent,
|
||||
DIALOG_EESCHEMA_PAGE_SETTINGS::DIALOG_EESCHEMA_PAGE_SETTINGS( EDA_DRAW_FRAME* aParent, EMBEDDED_FILES* aEmbeddedFiles,
|
||||
VECTOR2I aMaxUserSizeMils ) :
|
||||
DIALOG_PAGES_SETTINGS( aParent, schIUScale.IU_PER_MILS, aMaxUserSizeMils )
|
||||
DIALOG_PAGES_SETTINGS( aParent, aEmbeddedFiles, schIUScale.IU_PER_MILS, aMaxUserSizeMils )
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -22,11 +22,13 @@
|
||||
|
||||
#include <dialogs/dialog_page_settings.h>
|
||||
|
||||
class EMBEDDED_FILES;
|
||||
|
||||
|
||||
class DIALOG_EESCHEMA_PAGE_SETTINGS : public DIALOG_PAGES_SETTINGS
|
||||
{
|
||||
public:
|
||||
DIALOG_EESCHEMA_PAGE_SETTINGS( EDA_DRAW_FRAME* aParent, VECTOR2I aMaxUserSizeMils );
|
||||
DIALOG_EESCHEMA_PAGE_SETTINGS( EDA_DRAW_FRAME* aParent, EMBEDDED_FILES* aEmbeddedFiles, VECTOR2I aMaxUserSizeMils );
|
||||
virtual ~DIALOG_EESCHEMA_PAGE_SETTINGS();
|
||||
|
||||
private:
|
||||
|
@ -108,7 +108,7 @@ DIALOG_LABEL_PROPERTIES::DIALOG_LABEL_PROPERTIES( SCH_EDIT_FRAME* aParent, SCH_L
|
||||
m_grid->SetDefaultRowSize( m_grid->GetDefaultRowSize() + 4 );
|
||||
|
||||
m_grid->SetTable( m_fields );
|
||||
m_grid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this,
|
||||
m_grid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this, nullptr,
|
||||
[&]( wxCommandEvent& aEvent )
|
||||
{
|
||||
OnAddField( aEvent );
|
||||
|
@ -40,6 +40,7 @@
|
||||
|
||||
#include <dialog_sim_model.h>
|
||||
|
||||
#include <panel_embedded_files.h>
|
||||
#include <dialog_lib_symbol_properties.h>
|
||||
#include <settings/settings_manager.h>
|
||||
#include <symbol_editor_settings.h>
|
||||
@ -63,11 +64,14 @@ DIALOG_LIB_SYMBOL_PROPERTIES::DIALOG_LIB_SYMBOL_PROPERTIES( SYMBOL_EDIT_FRAME* a
|
||||
m_delayedFocusColumn( -1 ),
|
||||
m_delayedFocusPage( -1 )
|
||||
{
|
||||
m_embeddedFiles = new PANEL_EMBEDDED_FILES( m_NoteBook, m_libEntry );
|
||||
m_NoteBook->AddPage( m_embeddedFiles, _( "Embedded Files" ) );
|
||||
|
||||
// Give a bit more room for combobox editors
|
||||
m_grid->SetDefaultRowSize( m_grid->GetDefaultRowSize() + 4 );
|
||||
m_fields = new FIELDS_GRID_TABLE( this, aParent, m_grid, m_libEntry );
|
||||
m_grid->SetTable( m_fields );
|
||||
m_grid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this,
|
||||
m_grid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this, aLibEntry,
|
||||
[&]( wxCommandEvent& aEvent )
|
||||
{
|
||||
OnAddField( aEvent );
|
||||
@ -79,7 +83,7 @@ DIALOG_LIB_SYMBOL_PROPERTIES::DIALOG_LIB_SYMBOL_PROPERTIES( SYMBOL_EDIT_FRAME* a
|
||||
m_grid->ShowHideColumns( cfg->m_EditSymbolVisibleColumns );
|
||||
|
||||
wxGridCellAttr* attr = new wxGridCellAttr;
|
||||
attr->SetEditor( new GRID_CELL_URL_EDITOR( this, PROJECT_SCH::SchSearchS( &Prj() ) ) );
|
||||
attr->SetEditor( new GRID_CELL_URL_EDITOR( this, PROJECT_SCH::SchSearchS( &Prj() ), aLibEntry ) );
|
||||
m_grid->SetAttr( DATASHEET_FIELD, FDC_VALUE, attr );
|
||||
|
||||
m_SymbolNameCtrl->SetValidator( FIELD_VALIDATOR( VALUE_FIELD ) );
|
||||
@ -257,6 +261,8 @@ bool DIALOG_LIB_SYMBOL_PROPERTIES::TransferDataToWindow()
|
||||
|
||||
m_NoteBook->SetSelection( (unsigned) m_lastOpenedPage );
|
||||
|
||||
m_embeddedFiles->TransferDataToWindow();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -469,6 +475,7 @@ bool DIALOG_LIB_SYMBOL_PROPERTIES::TransferDataFromWindow()
|
||||
// occurs.
|
||||
m_Parent->SetShowDeMorgan( m_hasAlternateBodyStyles->GetValue() );
|
||||
|
||||
m_embeddedFiles->TransferDataFromWindow();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
class SYMBOL_EDIT_FRAME;
|
||||
class LIB_SYMBOL;
|
||||
class PANEL_EMBEDDED_FILES;
|
||||
class WX_GRID;
|
||||
|
||||
|
||||
@ -93,6 +94,8 @@ public:
|
||||
std::bitset<64> m_shownColumns;
|
||||
wxSize m_size;
|
||||
|
||||
PANEL_EMBEDDED_FILES* m_embeddedFiles;
|
||||
|
||||
private:
|
||||
static int m_lastOpenedPage; // To remember the last notebook selection
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <erc/erc_item.h>
|
||||
#include <panel_text_variables.h>
|
||||
#include <panel_bom_presets.h>
|
||||
#include <panel_embedded_files.h>
|
||||
#include <project/project_file.h>
|
||||
#include <project/net_settings.h>
|
||||
#include <settings/settings_manager.h>
|
||||
@ -121,6 +122,16 @@ DIALOG_SCHEMATIC_SETUP::DIALOG_SCHEMATIC_SETUP( SCH_EDIT_FRAME* aFrame ) :
|
||||
return new PANEL_TEXT_VARIABLES( aParent, &Prj() );
|
||||
}, _( "Text Variables" ) );
|
||||
|
||||
|
||||
m_treebook->AddPage( new wxPanel( GetTreebook() ), _( "Schematic Data" ) );
|
||||
|
||||
m_embeddedFilesPage = m_treebook->GetPageCount();
|
||||
m_treebook->AddLazySubPage(
|
||||
[this]( wxWindow* aParent ) -> wxWindow*
|
||||
{
|
||||
return new PANEL_EMBEDDED_FILES( aParent, &m_frame->Schematic() );
|
||||
}, _( "Embedded Files" ) );
|
||||
|
||||
for( size_t i = 0; i < m_treebook->GetPageCount(); ++i )
|
||||
m_treebook->ExpandNode( i );
|
||||
|
||||
|
@ -56,6 +56,7 @@ protected:
|
||||
size_t m_busesPage;
|
||||
size_t m_severitiesPage;
|
||||
size_t m_netclassesPage;
|
||||
size_t m_embeddedFilesPage;
|
||||
};
|
||||
|
||||
|
||||
|
@ -67,7 +67,7 @@ DIALOG_SHEET_PROPERTIES::DIALOG_SHEET_PROPERTIES( SCH_EDIT_FRAME* aParent, SCH_S
|
||||
m_grid->SetDefaultRowSize( m_grid->GetDefaultRowSize() + 4 );
|
||||
|
||||
m_grid->SetTable( m_fields );
|
||||
m_grid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this,
|
||||
m_grid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this, &aParent->Schematic(),
|
||||
[&]( wxCommandEvent& aEvent )
|
||||
{
|
||||
OnAddField( aEvent );
|
||||
|
@ -343,7 +343,8 @@ void DIALOG_SYMBOL_FIELDS_TABLE::SetupColumnProperties( int aCol )
|
||||
else if( m_dataModel->GetColFieldName( aCol ) == GetCanonicalFieldName( DATASHEET_FIELD ) )
|
||||
{
|
||||
// set datasheet column viewer button
|
||||
attr->SetEditor( new GRID_CELL_URL_EDITOR( this, PROJECT_SCH::SchSearchS( &Prj() ) ) );
|
||||
attr->SetEditor( new GRID_CELL_URL_EDITOR( this, PROJECT_SCH::SchSearchS( &Prj() ),
|
||||
&m_parent->Schematic() ) );
|
||||
m_grid->SetColAttr( aCol, attr );
|
||||
}
|
||||
else if( m_dataModel->ColIsQuantity( aCol ) || m_dataModel->ColIsItemNumber( aCol ) )
|
||||
|
@ -334,7 +334,7 @@ DIALOG_SYMBOL_PROPERTIES::DIALOG_SYMBOL_PROPERTIES( SCH_EDIT_FRAME* aParent,
|
||||
m_pinGrid->SetDefaultRowSize( m_pinGrid->GetDefaultRowSize() + 4 );
|
||||
|
||||
m_fieldsGrid->SetTable( m_fields );
|
||||
m_fieldsGrid->PushEventHandler( new FIELDS_GRID_TRICKS( m_fieldsGrid, this,
|
||||
m_fieldsGrid->PushEventHandler( new FIELDS_GRID_TRICKS( m_fieldsGrid, this, &aParent->Schematic(),
|
||||
[&]( wxCommandEvent& aEvent )
|
||||
{
|
||||
OnAddField( aEvent );
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <kiway.h>
|
||||
#include <symbol_edit_frame.h>
|
||||
#include <dialogs/panel_gal_display_options.h>
|
||||
#include <filename_resolver.h>
|
||||
#include <pgm_base.h>
|
||||
#include <project/project_file.h>
|
||||
#include <project/project_local_settings.h>
|
||||
@ -69,14 +70,6 @@ bool SCH_EDIT_FRAME::LoadProjectSettings()
|
||||
|
||||
BASE_SCREEN::m_DrawingSheetFileName = settings.m_SchDrawingSheetFileName;
|
||||
|
||||
// Load the drawing sheet from the filename stored in BASE_SCREEN::m_DrawingSheetFileName.
|
||||
// If empty, or not existing, the default drawing sheet is loaded.
|
||||
wxString filename = DS_DATA_MODEL::ResolvePath( BASE_SCREEN::m_DrawingSheetFileName,
|
||||
Prj().GetProjectPath() );
|
||||
|
||||
if( !DS_DATA_MODEL::GetTheInstance().LoadDrawingSheet( filename, nullptr ) )
|
||||
ShowInfoBarError( _( "Error loading drawing sheet." ), true );
|
||||
|
||||
PROJECT_LOCAL_SETTINGS& localSettings = Prj().GetLocalSettings();
|
||||
|
||||
EE_SELECTION_TOOL* selTool = GetToolManager()->GetTool<EE_SELECTION_TOOL>();
|
||||
@ -87,6 +80,26 @@ bool SCH_EDIT_FRAME::LoadProjectSettings()
|
||||
}
|
||||
|
||||
|
||||
void SCH_EDIT_FRAME::LoadDrawingSheet()
|
||||
{
|
||||
// Load the drawing sheet from the filename stored in BASE_SCREEN::m_DrawingSheetFileName.
|
||||
// If empty, or not existing, the default drawing sheet is loaded.
|
||||
|
||||
SCHEMATIC_SETTINGS& settings = Schematic().Settings();
|
||||
FILENAME_RESOLVER resolver;
|
||||
resolver.SetProject( &Prj() );
|
||||
resolver.SetProgramBase( &Pgm() );
|
||||
|
||||
wxString filename = resolver.ResolvePath( settings.m_SchDrawingSheetFileName,
|
||||
Prj().GetProjectPath(),
|
||||
Schematic().GetEmbeddedFiles() );
|
||||
wxString msg;
|
||||
|
||||
if( !DS_DATA_MODEL::GetTheInstance().LoadDrawingSheet( filename, &msg ) )
|
||||
ShowInfoBarError( msg, true );
|
||||
}
|
||||
|
||||
|
||||
void SCH_EDIT_FRAME::ShowSchematicSetupDialog( const wxString& aInitialPage )
|
||||
{
|
||||
SCH_SCREENS screens( Schematic().Root() );
|
||||
@ -177,15 +190,20 @@ void SCH_EDIT_FRAME::saveProjectSettings()
|
||||
|
||||
if( !BASE_SCREEN::m_DrawingSheetFileName.IsEmpty() )
|
||||
{
|
||||
wxFileName layoutfn( DS_DATA_MODEL::ResolvePath( BASE_SCREEN::m_DrawingSheetFileName,
|
||||
Prj().GetProjectPath() ) );
|
||||
FILENAME_RESOLVER resolve;
|
||||
resolve.SetProject( &Prj() );
|
||||
resolve.SetProgramBase( &Pgm() );
|
||||
|
||||
wxFileName layoutfn( resolve.ResolvePath( BASE_SCREEN::m_DrawingSheetFileName,
|
||||
Prj().GetProjectPath(),
|
||||
Schematic().GetEmbeddedFiles() ) );
|
||||
|
||||
bool success = true;
|
||||
|
||||
if( !layoutfn.IsAbsolute() )
|
||||
success = layoutfn.MakeAbsolute( Prj().GetProjectPath() );
|
||||
|
||||
if( success && layoutfn.IsOk() && !layoutfn.FileExists() )
|
||||
if( success && layoutfn.IsOk() && !layoutfn.FileExists() && layoutfn.HasName() )
|
||||
{
|
||||
if( layoutfn.DirExists() && layoutfn.IsDirWritable() )
|
||||
DS_DATA_MODEL::GetTheInstance().Save( layoutfn.GetFullPath() );
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <memory>
|
||||
#include <connection_graph.h>
|
||||
#include "eeschema_helpers.h"
|
||||
#include <filename_resolver.h>
|
||||
#include <kiway.h>
|
||||
#include <sch_painter.h>
|
||||
#include <locale_io.h>
|
||||
@ -111,9 +112,14 @@ void EESCHEMA_JOBS_HANDLER::InitRenderSettings( SCH_RENDER_SETTINGS* aRenderSett
|
||||
auto loadSheet =
|
||||
[&]( const wxString& path ) -> bool
|
||||
{
|
||||
wxString absolutePath = DS_DATA_MODEL::ResolvePath( path,
|
||||
aSch->Prj().GetProjectPath() );
|
||||
wxString msg;
|
||||
FILENAME_RESOLVER resolve;
|
||||
resolve.SetProject( &aSch->Prj() );
|
||||
resolve.SetProgramBase( &Pgm() );
|
||||
|
||||
wxString absolutePath = resolve.ResolvePath( path,
|
||||
wxGetCwd(),
|
||||
aSch->GetEmbeddedFiles() );
|
||||
|
||||
if( !DS_DATA_MODEL::GetTheInstance().LoadDrawingSheet( absolutePath, &msg ) )
|
||||
{
|
||||
|
@ -21,6 +21,7 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <embedded_files.h>
|
||||
#include <kiway.h>
|
||||
#include <kiway_player.h>
|
||||
#include <dialog_shim.h>
|
||||
@ -238,8 +239,16 @@ void FIELDS_GRID_TABLE::initGrid( WX_GRID* aGrid )
|
||||
fpIdEditor->SetValidator( m_nonUrlValidator );
|
||||
m_footprintAttr->SetEditor( fpIdEditor );
|
||||
|
||||
EMBEDDED_FILES* files = nullptr;
|
||||
|
||||
if( m_frame->GetFrameType() == FRAME_SCH )
|
||||
files = m_frame->GetScreen()->Schematic();
|
||||
else if( m_frame->GetFrameType() == FRAME_SCH_SYMBOL_EDITOR || m_frame->GetFrameType() == FRAME_SCH_VIEWER )
|
||||
files = m_part;
|
||||
|
||||
m_urlAttr = new wxGridCellAttr;
|
||||
GRID_CELL_URL_EDITOR* urlEditor = new GRID_CELL_URL_EDITOR( m_dialog, PROJECT_SCH::SchSearchS( &m_frame->Prj() ) );
|
||||
GRID_CELL_URL_EDITOR* urlEditor =
|
||||
new GRID_CELL_URL_EDITOR( m_dialog, PROJECT_SCH::SchSearchS( &m_frame->Prj() ), files );
|
||||
urlEditor->SetValidator( m_urlValidator );
|
||||
m_urlAttr->SetEditor( urlEditor );
|
||||
|
||||
@ -292,6 +301,9 @@ void FIELDS_GRID_TABLE::initGrid( WX_GRID* aGrid )
|
||||
SCH_EDIT_FRAME* editFrame = dynamic_cast<SCH_EDIT_FRAME*>( m_frame );
|
||||
wxArrayString existingNetclasses;
|
||||
|
||||
wxArrayString fonts;
|
||||
std::vector<std::string> fontNames;
|
||||
|
||||
if( editFrame )
|
||||
{
|
||||
// Load the combobox with existing existingNetclassNames
|
||||
@ -302,15 +314,30 @@ void FIELDS_GRID_TABLE::initGrid( WX_GRID* aGrid )
|
||||
|
||||
for( const auto& [ name, netclass ] : settings->m_NetClasses )
|
||||
existingNetclasses.push_back( name );
|
||||
|
||||
// We don't need to re-cache the embedded fonts when looking at symbols in the schematic editor
|
||||
// because the fonts are all available in the schematic.
|
||||
const std::vector<wxString>* fontFiles = nullptr;
|
||||
|
||||
if( m_frame->GetScreen() && m_frame->GetScreen()->Schematic() )
|
||||
fontFiles = m_frame->GetScreen()->Schematic()->GetEmbeddedFiles()->GetFontFiles();
|
||||
|
||||
Fontconfig()->ListFonts( fontNames, std::string( Pgm().GetLanguageTag().utf8_str() ),
|
||||
fontFiles, false );
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::vector<wxString>* fontFiles = m_part->GetEmbeddedFiles()->UpdateFontFiles();
|
||||
|
||||
// If there are font files embedded, we want to re-cache our fonts for each symbol that we
|
||||
// are looking at in the symbol editor.
|
||||
Fontconfig()->ListFonts( fontNames, std::string( Pgm().GetLanguageTag().utf8_str() ),
|
||||
fontFiles, !fontFiles->empty() );
|
||||
}
|
||||
|
||||
m_netclassAttr = new wxGridCellAttr;
|
||||
m_netclassAttr->SetEditor( new GRID_CELL_COMBOBOX( existingNetclasses ) );
|
||||
|
||||
wxArrayString fonts;
|
||||
std::vector<std::string> fontNames;
|
||||
Fontconfig()->ListFonts( fontNames, std::string( Pgm().GetLanguageTag().utf8_str() ) );
|
||||
|
||||
for( const std::string& name : fontNames )
|
||||
fonts.Add( wxString( name ) );
|
||||
|
||||
@ -931,8 +958,9 @@ void FIELDS_GRID_TRICKS::doPopupSelection( wxCommandEvent& event )
|
||||
else if (event.GetId() == MYID_SHOW_DATASHEET )
|
||||
{
|
||||
wxString datasheet_uri = m_grid->GetCellValue( DATASHEET_FIELD, FDC_VALUE );
|
||||
|
||||
GetAssociatedDocument( m_dlg, datasheet_uri, &m_dlg->Prj(),
|
||||
PROJECT_SCH::SchSearchS( &m_dlg->Prj() ) );
|
||||
PROJECT_SCH::SchSearchS( &m_dlg->Prj() ), m_files );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -31,22 +31,25 @@
|
||||
|
||||
class SCH_BASE_FRAME;
|
||||
class DIALOG_SHIM;
|
||||
class EMBEDDED_FILES;
|
||||
class SCH_LABEL_BASE;
|
||||
|
||||
|
||||
class FIELDS_GRID_TRICKS : public GRID_TRICKS
|
||||
{
|
||||
public:
|
||||
FIELDS_GRID_TRICKS( WX_GRID* aGrid, DIALOG_SHIM* aDialog,
|
||||
FIELDS_GRID_TRICKS( WX_GRID* aGrid, DIALOG_SHIM* aDialog, EMBEDDED_FILES* aFiles,
|
||||
std::function<void( wxCommandEvent& )> aAddHandler ) :
|
||||
GRID_TRICKS( aGrid, std::move( aAddHandler ) ),
|
||||
m_dlg( aDialog )
|
||||
m_dlg( aDialog ),
|
||||
m_files( aFiles )
|
||||
{}
|
||||
|
||||
protected:
|
||||
void showPopupMenu( wxMenu& menu, wxGridEvent& aEvent ) override;
|
||||
void doPopupSelection( wxCommandEvent& event ) override;
|
||||
DIALOG_SHIM* m_dlg;
|
||||
EMBEDDED_FILES* m_files;
|
||||
};
|
||||
|
||||
|
||||
|
@ -517,6 +517,11 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
|
||||
}
|
||||
}
|
||||
|
||||
// After the schematic is successfully loaded, we load the drawing sheet.
|
||||
// This allows us to use the drawing sheet embedded in the schematic (if any)
|
||||
// instead of the default one.
|
||||
LoadDrawingSheet();
|
||||
|
||||
schematic.PruneOrphanedSymbolInstances( Prj().GetProjectName(), sheetList );
|
||||
schematic.PruneOrphanedSheetInstances( Prj().GetProjectName(), sheetList );
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <font/outline_font.h>
|
||||
#include <sch_draw_panel.h>
|
||||
#include <plotters/plotter.h>
|
||||
#include <sch_screen.h>
|
||||
@ -1872,3 +1873,50 @@ double LIB_SYMBOL::Similarity( const SCH_ITEM& aOther ) const
|
||||
|
||||
return similarity;
|
||||
}
|
||||
|
||||
|
||||
EMBEDDED_FILES* LIB_SYMBOL::GetEmbeddedFiles()
|
||||
{
|
||||
return static_cast<EMBEDDED_FILES*>( this );
|
||||
}
|
||||
|
||||
|
||||
const EMBEDDED_FILES* LIB_SYMBOL::GetEmbeddedFiles() const
|
||||
{
|
||||
return static_cast<const EMBEDDED_FILES*>( this );
|
||||
}
|
||||
|
||||
|
||||
void LIB_SYMBOL::EmbedFonts()
|
||||
{
|
||||
using OUTLINE_FONT = KIFONT::OUTLINE_FONT;
|
||||
using EMBEDDING_PERMISSION = OUTLINE_FONT::EMBEDDING_PERMISSION;
|
||||
|
||||
std::set<OUTLINE_FONT*> fonts;
|
||||
|
||||
for( SCH_ITEM& item : m_drawings )
|
||||
{
|
||||
if( item.Type() == SCH_TEXT_T )
|
||||
{
|
||||
auto* text = static_cast<SCH_TEXT*>( &item );
|
||||
|
||||
if( auto* font = text->GetFont(); font && !font->IsStroke() )
|
||||
{
|
||||
auto* outline = static_cast<OUTLINE_FONT*>( font );
|
||||
auto permission = outline->GetEmbeddingPermission();
|
||||
|
||||
if( permission == EMBEDDING_PERMISSION::EDITABLE
|
||||
|| permission == EMBEDDING_PERMISSION::INSTALLABLE )
|
||||
{
|
||||
fonts.insert( outline );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( auto* font : fonts )
|
||||
{
|
||||
auto file = GetEmbeddedFiles()->AddFile( font->GetFileName(), false );
|
||||
file->type = EMBEDDED_FILES::EMBEDDED_FILE::FILE_TYPE::FONT;
|
||||
}
|
||||
}
|
@ -27,6 +27,7 @@
|
||||
#ifndef LIB_SYMBOL_H
|
||||
#define LIB_SYMBOL_H
|
||||
|
||||
#include <embedded_files.h>
|
||||
#include <symbol.h>
|
||||
#include <sch_field.h>
|
||||
#include <sch_pin.h>
|
||||
@ -73,7 +74,7 @@ struct LIB_SYMBOL_UNIT
|
||||
* A library symbol object is typically saved and loaded in a symbol library file (.lib).
|
||||
* Library symbols are different from schematic symbols.
|
||||
*/
|
||||
class LIB_SYMBOL : public SYMBOL, public LIB_TREE_ITEM
|
||||
class LIB_SYMBOL : public SYMBOL, public LIB_TREE_ITEM, public EMBEDDED_FILES
|
||||
{
|
||||
public:
|
||||
LIB_SYMBOL( const wxString& aName, LIB_SYMBOL* aParent = nullptr,
|
||||
@ -333,6 +334,11 @@ public:
|
||||
return GetValueField().GetText();
|
||||
}
|
||||
|
||||
EMBEDDED_FILES* GetEmbeddedFiles() override;
|
||||
const EMBEDDED_FILES* GetEmbeddedFiles() const;
|
||||
|
||||
void EmbedFonts() override;
|
||||
|
||||
void RunOnChildren( const std::function<void( SCH_ITEM* )>& aFunction ) override;
|
||||
|
||||
/**
|
||||
|
@ -66,6 +66,7 @@
|
||||
#include <tool/action_toolbar.h>
|
||||
#include <tool/common_control.h>
|
||||
#include <tool/common_tools.h>
|
||||
#include <tool/embed_tool.h>
|
||||
#include <tool/picker_tool.h>
|
||||
#include <tool/properties_tool.h>
|
||||
#include <tool/selection.h>
|
||||
@ -368,6 +369,7 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||
}
|
||||
|
||||
LoadProjectSettings();
|
||||
LoadDrawingSheet();
|
||||
|
||||
view->SetLayerVisible( LAYER_ERC_ERR, cfg->m_Appearance.show_erc_errors );
|
||||
view->SetLayerVisible( LAYER_ERC_WARN, cfg->m_Appearance.show_erc_warnings );
|
||||
@ -524,6 +526,7 @@ void SCH_EDIT_FRAME::setupTools()
|
||||
m_toolManager->RegisterTool( new EE_POINT_EDITOR );
|
||||
m_toolManager->RegisterTool( new SCH_NAVIGATE_TOOL );
|
||||
m_toolManager->RegisterTool( new PROPERTIES_TOOL );
|
||||
m_toolManager->RegisterTool( new EMBED_TOOL );
|
||||
m_toolManager->InitTools();
|
||||
|
||||
// Run the selection tool, it is supposed to be always active
|
||||
|
@ -159,6 +159,11 @@ public:
|
||||
*/
|
||||
bool LoadProjectSettings();
|
||||
|
||||
/**
|
||||
* Load the drawing sheet file.
|
||||
*/
|
||||
void LoadDrawingSheet();
|
||||
|
||||
void ShowSchematicSetupDialog( const wxString& aInitialPage = wxEmptyString );
|
||||
|
||||
void LoadSettings( APP_SETTINGS_BASE* aCfg ) override;
|
||||
|
@ -49,7 +49,8 @@
|
||||
//#define SEXPR_SYMBOL_LIB_FILE_VERSION 20220914 // Symbol unit display names.
|
||||
//#define SEXPR_SYMBOL_LIB_FILE_VERSION 20220914 // Don't save property ID
|
||||
//#define SEXPR_SYMBOL_LIB_FILE_VERSION 20230620 // ki_description -> Description Field
|
||||
#define SEXPR_SYMBOL_LIB_FILE_VERSION 20231120 // generator_version; V8 cleanups
|
||||
//#define SEXPR_SYMBOL_LIB_FILE_VERSION 20231120 // generator_version; V8 cleanups
|
||||
#define SEXPR_SYMBOL_LIB_FILE_VERSION 20240529 // Embedded Files
|
||||
|
||||
/**
|
||||
* Schematic file version.
|
||||
@ -105,4 +106,5 @@
|
||||
//#define SEXPR_SCHEMATIC_FILE_VERSION 20231120 // generator_version; V8 cleanups
|
||||
//#define SEXPR_SCHEMATIC_FILE_VERSION 20240101 // Tables.
|
||||
//#define SEXPR_SCHEMATIC_FILE_VERSION 20240417 // Rule areas
|
||||
#define SEXPR_SCHEMATIC_FILE_VERSION 20240602 // Sheet attributes
|
||||
//#define SEXPR_SCHEMATIC_FILE_VERSION 20240602 // Sheet attributes
|
||||
#define SEXPR_SCHEMATIC_FILE_VERSION 20240620 // Embedded Files
|
||||
|
@ -372,6 +372,14 @@ void SCH_IO_KICAD_SEXPR::Format( SCH_SHEET* aSheet )
|
||||
|
||||
wxCHECK( screen, /* void */ );
|
||||
|
||||
// If we've requested to embed the fonts in the schematic, do so.
|
||||
// Otherwise, clear the embedded fonts from the schematic. Embedded
|
||||
// fonts will be used if available
|
||||
if( m_schematic->GetAreFontsEmbedded() )
|
||||
m_schematic->EmbedFonts();
|
||||
else
|
||||
m_schematic->GetEmbeddedFiles()->ClearEmbeddedFonts();
|
||||
|
||||
m_out->Print( 0, "(kicad_sch (version %d) (generator \"eeschema\") (generator_version \"%s\")\n\n",
|
||||
SEXPR_SCHEMATIC_FILE_VERSION, GetMajorMinorVersion().c_str().AsChar() );
|
||||
|
||||
@ -477,7 +485,7 @@ void SCH_IO_KICAD_SEXPR::Format( SCH_SHEET* aSheet )
|
||||
case SCH_SHAPE_T:
|
||||
saveShape( static_cast<SCH_SHAPE*>( item ), 1 );
|
||||
break;
|
||||
|
||||
|
||||
case SCH_RULE_AREA_T:
|
||||
saveRuleArea( static_cast<SCH_RULE_AREA*>( item ), 1 );
|
||||
break;
|
||||
@ -509,6 +517,13 @@ void SCH_IO_KICAD_SEXPR::Format( SCH_SHEET* aSheet )
|
||||
|
||||
instances.emplace_back( aSheet->GetRootInstance() );
|
||||
saveInstances( instances, 1 );
|
||||
|
||||
m_out->Print( 1, "(embedded_fonts %s)\n",
|
||||
m_schematic->GetAreFontsEmbedded() ? "yes" : "no" );
|
||||
|
||||
// Save any embedded files
|
||||
if( !m_schematic->GetEmbeddedFiles()->IsEmpty() )
|
||||
m_schematic->WriteEmbeddedFiles( *m_out, 1, true );
|
||||
}
|
||||
|
||||
m_out->Print( 0, ")\n" );
|
||||
@ -527,6 +542,14 @@ void SCH_IO_KICAD_SEXPR::Format( EE_SELECTION* aSelection, SCH_SHEET_PATH* aSele
|
||||
m_schematic = &aSchematic;
|
||||
m_out = aFormatter;
|
||||
|
||||
// If we've requested to embed the fonts in the schematic, do so.
|
||||
// Otherwise, clear the embedded fonts from the schematic. Embedded
|
||||
// fonts will be used if available
|
||||
if( m_schematic->GetAreFontsEmbedded() )
|
||||
m_schematic->EmbedFonts();
|
||||
else
|
||||
m_schematic->GetEmbeddedFiles()->ClearEmbeddedFonts();
|
||||
|
||||
size_t i;
|
||||
SCH_ITEM* item;
|
||||
std::map<wxString, LIB_SYMBOL*> libSymbols;
|
||||
@ -564,7 +587,7 @@ void SCH_IO_KICAD_SEXPR::Format( EE_SELECTION* aSelection, SCH_SHEET_PATH* aSele
|
||||
for( const std::pair<const wxString, LIB_SYMBOL*>& libSymbol : libSymbols )
|
||||
{
|
||||
SCH_IO_KICAD_SEXPR_LIB_CACHE::SaveSymbol( libSymbol.second, *m_out, 1,
|
||||
libSymbol.first );
|
||||
libSymbol.first, false );
|
||||
}
|
||||
|
||||
m_out->Print( 0, ")\n\n" );
|
||||
|
@ -130,7 +130,7 @@ void SCH_IO_KICAD_SEXPR_LIB_CACHE::Save( const std::optional<bool>& aOpt )
|
||||
|
||||
|
||||
void SCH_IO_KICAD_SEXPR_LIB_CACHE::SaveSymbol( LIB_SYMBOL* aSymbol, OUTPUTFORMATTER& aFormatter,
|
||||
int aNestLevel, const wxString& aLibName )
|
||||
int aNestLevel, const wxString& aLibName, bool aIncludeData )
|
||||
{
|
||||
wxCHECK_RET( aSymbol, "Invalid LIB_SYMBOL pointer." );
|
||||
|
||||
@ -138,6 +138,15 @@ void SCH_IO_KICAD_SEXPR_LIB_CACHE::SaveSymbol( LIB_SYMBOL* aSymbol, OUTPUTFORMAT
|
||||
wxCHECK2( wxLocale::GetInfo( wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER ) == ".",
|
||||
LOCALE_IO toggle );
|
||||
|
||||
|
||||
// If we've requested to embed the fonts in the symbol, do so.
|
||||
// Otherwise, clear the embedded fonts from the symbol. Embedded
|
||||
// fonts will be used if available
|
||||
if( aSymbol->GetAreFontsEmbedded() )
|
||||
aSymbol->EmbedFonts();
|
||||
else
|
||||
aSymbol->GetEmbeddedFiles()->ClearEmbeddedFonts();
|
||||
|
||||
int nextFreeFieldId = MANDATORY_FIELDS;
|
||||
std::vector<SCH_FIELD*> fields;
|
||||
std::string name = aFormatter.Quotew( aSymbol->GetLibId().GetLibItemName().wx_str() );
|
||||
@ -262,6 +271,12 @@ void SCH_IO_KICAD_SEXPR_LIB_CACHE::SaveSymbol( LIB_SYMBOL* aSymbol, OUTPUTFORMAT
|
||||
|
||||
aFormatter.Print( aNestLevel + 1, ")\n" );
|
||||
}
|
||||
|
||||
aFormatter.Print( aNestLevel + 1, "(embedded_fonts %s)\n",
|
||||
aSymbol->GetAreFontsEmbedded() ? "yes" : "no" );
|
||||
|
||||
if( !aSymbol->EmbeddedFileMap().empty() )
|
||||
aSymbol->WriteEmbeddedFiles( aFormatter, aNestLevel + 1, aIncludeData );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -51,8 +51,8 @@ public:
|
||||
|
||||
void DeleteSymbol( const wxString& aName ) override;
|
||||
|
||||
static void SaveSymbol( LIB_SYMBOL* aSymbol, OUTPUTFORMATTER& aFormatter,
|
||||
int aNestLevel = 0, const wxString& aLibName = wxEmptyString );
|
||||
static void SaveSymbol( LIB_SYMBOL* aSymbol, OUTPUTFORMATTER& aFormatter, int aNestLevel = 0,
|
||||
const wxString& aLibName = wxEmptyString, bool aIncludeData = true );
|
||||
|
||||
void SetFileFormatVersionAtLoad( int aVersion ) { m_fileFormatVersionAtLoad = aVersion; }
|
||||
int GetFileFormatVersionAtLoad() const { return m_fileFormatVersionAtLoad; }
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <fmt/format.h>
|
||||
#define wxUSE_BASE64 1
|
||||
#include <wx/base64.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/mstream.h>
|
||||
#include <wx/tokenzr.h>
|
||||
|
||||
@ -39,6 +40,8 @@
|
||||
#include <sch_pin.h>
|
||||
#include <math/util.h> // KiROUND, Clamp
|
||||
#include <font/font.h>
|
||||
#include <font/fontconfig.h>
|
||||
#include <pgm_base.h>
|
||||
#include <string_utils.h>
|
||||
#include <sch_bitmap.h>
|
||||
#include <sch_bus_entry.h>
|
||||
@ -274,6 +277,13 @@ LIB_SYMBOL* SCH_IO_KICAD_SEXPR_PARSER::ParseSymbol( LIB_SYMBOL_MAP& aSymbolLibMa
|
||||
}
|
||||
}
|
||||
|
||||
for( auto& [text, params] : m_fontTextMap )
|
||||
{
|
||||
text->SetFont( KIFONT::FONT::GetFont( std::get<0>( params ), std::get<1>( params ),
|
||||
std::get<2>( params ),
|
||||
newSymbol->GetEmbeddedFiles()->UpdateFontFiles() ) );
|
||||
}
|
||||
|
||||
return newSymbol;
|
||||
}
|
||||
|
||||
@ -534,6 +544,31 @@ LIB_SYMBOL* SCH_IO_KICAD_SEXPR_PARSER::parseLibSymbol( LIB_SYMBOL_MAP& aSymbolLi
|
||||
symbol->AddDrawItem( item, false );
|
||||
break;
|
||||
|
||||
case T_embedded_fonts:
|
||||
{
|
||||
symbol->SetAreFontsEmbedded( parseBool() );
|
||||
NeedRIGHT();
|
||||
break;
|
||||
}
|
||||
|
||||
case T_embedded_files:
|
||||
{
|
||||
EMBEDDED_FILES_PARSER embeddedFilesParser( reader );
|
||||
embeddedFilesParser.SyncLineReaderWith( *this );
|
||||
|
||||
try
|
||||
{
|
||||
embeddedFilesParser.ParseEmbedded( symbol->GetEmbeddedFiles() );
|
||||
}
|
||||
catch( const IO_ERROR& e )
|
||||
{
|
||||
wxLogError( e.What() );
|
||||
}
|
||||
|
||||
SyncLineReaderWith( embeddedFilesParser );
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
Expecting( "pin_names, pin_numbers, arc, bezier, circle, pin, polyline, "
|
||||
"rectangle, or text" );
|
||||
@ -742,7 +777,7 @@ void SCH_IO_KICAD_SEXPR_PARSER::parseEDA_TEXT( EDA_TEXT* aText, bool aConvertOve
|
||||
}
|
||||
|
||||
if( !faceName.IsEmpty() )
|
||||
aText->SetFont( KIFONT::FONT::GetFont( faceName, bold, italic ) );
|
||||
m_fontTextMap[aText] = { faceName, bold, italic };
|
||||
|
||||
break;
|
||||
|
||||
@ -2755,10 +2790,48 @@ void SCH_IO_KICAD_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet, bool aIsCopya
|
||||
parseBusAlias( screen );
|
||||
break;
|
||||
|
||||
case T_embedded_fonts:
|
||||
{
|
||||
SCHEMATIC* schematic = aSheet->Schematic();
|
||||
|
||||
if( !schematic )
|
||||
THROW_PARSE_ERROR( _( "No schematic object" ), CurSource(), CurLine(),
|
||||
CurLineNumber(), CurOffset() );
|
||||
|
||||
schematic->GetEmbeddedFiles()->SetAreFontsEmbedded( parseBool() );
|
||||
NeedRIGHT();
|
||||
break;
|
||||
}
|
||||
|
||||
case T_embedded_files:
|
||||
{
|
||||
SCHEMATIC* schematic = aSheet->Schematic();
|
||||
|
||||
if( !schematic )
|
||||
THROW_PARSE_ERROR( _( "No schematic object" ), CurSource(), CurLine(),
|
||||
CurLineNumber(), CurOffset() );
|
||||
|
||||
EMBEDDED_FILES_PARSER embeddedFilesParser( reader );
|
||||
embeddedFilesParser.SyncLineReaderWith( *this );
|
||||
|
||||
try
|
||||
{
|
||||
embeddedFilesParser.ParseEmbedded( schematic->GetEmbeddedFiles() );
|
||||
}
|
||||
catch( const PARSE_ERROR& e )
|
||||
{
|
||||
wxLogError( e.What() );
|
||||
}
|
||||
|
||||
SyncLineReaderWith( embeddedFilesParser );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
Expecting( "symbol, paper, page, title_block, bitmap, sheet, junction, no_connect, "
|
||||
"bus_entry, line, bus, text, label, class_label, global_label, "
|
||||
"hierarchical_label, symbol_instances, rule_area, or bus_alias" );
|
||||
Expecting( "bitmap, bus, bus_alias, bus_entry, class_label, embedded_files, global_label, "
|
||||
"hierarchical_label, junction, label, line, no_connect, page, paper, rule_area, "
|
||||
"sheet, symbol, symbol_instances, text, title_block" );
|
||||
}
|
||||
}
|
||||
|
||||
@ -2771,6 +2844,26 @@ void SCH_IO_KICAD_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet, bool aIsCopya
|
||||
}
|
||||
|
||||
screen->UpdateLocalLibSymbolLinks();
|
||||
screen->FixupEmbeddedData();
|
||||
|
||||
SCHEMATIC* schematic = aSheet->Schematic();
|
||||
|
||||
if( !schematic )
|
||||
THROW_PARSE_ERROR( _( "No schematic object" ), CurSource(), CurLine(),
|
||||
CurLineNumber(), CurOffset() );
|
||||
|
||||
for( auto& [text, params] : m_fontTextMap )
|
||||
{
|
||||
text->SetFont( KIFONT::FONT::GetFont( std::get<0>( params ), std::get<1>( params ),
|
||||
std::get<2>( params ),
|
||||
schematic->GetEmbeddedFiles()->UpdateFontFiles() ) );
|
||||
}
|
||||
|
||||
// When loading the schematic, take a moment to cache the fonts so that the font
|
||||
// picker can show the embedded fonts immediately.
|
||||
std::vector<std::string> fontNames;
|
||||
Fontconfig()->ListFonts( fontNames, std::string( Pgm().GetLanguageTag().utf8_str() ),
|
||||
schematic->GetEmbeddedFiles()->GetFontFiles(), true );
|
||||
|
||||
if( m_requiredVersion < 20200828 )
|
||||
screen->SetLegacySymbolInstanceData();
|
||||
|
@ -244,6 +244,8 @@ private:
|
||||
|
||||
std::set<KIID> m_uuids;
|
||||
|
||||
std::map<EDA_TEXT*, std::tuple<wxString, bool, bool>> m_fontTextMap;
|
||||
|
||||
PROGRESS_REPORTER* m_progressReporter; // optional; may be nullptr
|
||||
const LINE_READER* m_lineReader; // for progress reporting
|
||||
unsigned m_lastProgressLine;
|
||||
|
@ -1488,6 +1488,28 @@ void SCH_SCREEN::AddLibSymbol( LIB_SYMBOL* aLibSymbol )
|
||||
}
|
||||
|
||||
|
||||
void SCH_SCREEN::FixupEmbeddedData()
|
||||
{
|
||||
SCHEMATIC* schematic = Schematic();
|
||||
|
||||
for( auto& [name, libSym] : m_libSymbols )
|
||||
{
|
||||
for( auto& [filename, embeddedFile] : libSym->EmbeddedFileMap() )
|
||||
{
|
||||
EMBEDDED_FILES::EMBEDDED_FILE* file = schematic->GetEmbeddedFile( filename );
|
||||
|
||||
if( file )
|
||||
{
|
||||
embeddedFile->compressedEncodedData = file->compressedEncodedData;
|
||||
embeddedFile->decompressedData = file->decompressedData;
|
||||
embeddedFile->data_sha = file->data_sha;
|
||||
embeddedFile->is_valid = file->is_valid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SCH_SCREEN::AddBusAlias( std::shared_ptr<BUS_ALIAS> aAlias )
|
||||
{
|
||||
m_aliases.insert( aAlias );
|
||||
|
@ -490,6 +490,13 @@ public:
|
||||
*/
|
||||
void AddLibSymbol( LIB_SYMBOL* aLibSymbol );
|
||||
|
||||
/**
|
||||
* After loading a file from disk, the library symbols do not yet contain the full
|
||||
* data for their embedded files, only a reference. This iterates over all lib symbols
|
||||
* in the schematic and updates the library symbols with the full data.
|
||||
*/
|
||||
void FixupEmbeddedData();
|
||||
|
||||
/**
|
||||
* Add a bus alias definition (and transfers ownership of the pointer).
|
||||
*/
|
||||
|
@ -24,18 +24,21 @@
|
||||
#include <core/kicad_algo.h>
|
||||
#include <ee_collectors.h>
|
||||
#include <erc/erc_settings.h>
|
||||
#include <sch_marker.h>
|
||||
#include <font/outline_font.h>
|
||||
#include <netlist_exporter_spice.h>
|
||||
#include <project.h>
|
||||
#include <project/project_file.h>
|
||||
#include <project/net_settings.h>
|
||||
#include <project/project_file.h>
|
||||
#include <schematic.h>
|
||||
#include <sch_junction.h>
|
||||
#include <sch_label.h>
|
||||
#include <sch_line.h>
|
||||
#include <sch_marker.h>
|
||||
#include <sch_screen.h>
|
||||
#include <sim/spice_settings.h>
|
||||
#include <sch_label.h>
|
||||
#include <sim/spice_value.h>
|
||||
#include <netlist_exporter_spice.h>
|
||||
|
||||
#include <wx/log.h>
|
||||
|
||||
bool SCHEMATIC::m_IsSchematicExists = false;
|
||||
|
||||
@ -846,3 +849,59 @@ void SCHEMATIC::ResolveERCExclusionsPostUpdate()
|
||||
RootScreen()->Append( marker );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EMBEDDED_FILES* SCHEMATIC::GetEmbeddedFiles()
|
||||
{
|
||||
return static_cast<EMBEDDED_FILES*>( this );
|
||||
}
|
||||
|
||||
|
||||
const EMBEDDED_FILES* SCHEMATIC::GetEmbeddedFiles() const
|
||||
{
|
||||
return static_cast<const EMBEDDED_FILES*>( this );
|
||||
}
|
||||
|
||||
|
||||
void SCHEMATIC::EmbedFonts()
|
||||
{
|
||||
std::set<KIFONT::OUTLINE_FONT*> fonts;
|
||||
|
||||
SCH_SHEET_LIST sheetList = BuildUnorderedSheetList();
|
||||
|
||||
for( const SCH_SHEET_PATH& sheet : sheetList )
|
||||
{
|
||||
for( SCH_ITEM* item : sheet.LastScreen()->Items() )
|
||||
{
|
||||
if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( item ) )
|
||||
{
|
||||
KIFONT::FONT* font = text->GetFont();
|
||||
|
||||
if( !font || font->IsStroke() )
|
||||
continue;
|
||||
|
||||
using EMBEDDING_PERMISSION = KIFONT::OUTLINE_FONT::EMBEDDING_PERMISSION;
|
||||
auto* outline = static_cast<KIFONT::OUTLINE_FONT*>( font );
|
||||
|
||||
if( outline->GetEmbeddingPermission() == EMBEDDING_PERMISSION::EDITABLE
|
||||
|| outline->GetEmbeddingPermission() == EMBEDDING_PERMISSION::INSTALLABLE )
|
||||
{
|
||||
fonts.insert( outline );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( KIFONT::OUTLINE_FONT* font : fonts )
|
||||
{
|
||||
auto file = GetEmbeddedFiles()->AddFile( font->GetFileName(), false );
|
||||
|
||||
if( !file )
|
||||
{
|
||||
wxLogTrace( "EMBED", "Failed to add font file: %s", font->GetFileName() );
|
||||
continue;
|
||||
}
|
||||
|
||||
file->type = EMBEDDED_FILES::EMBEDDED_FILE::FILE_TYPE::FONT;
|
||||
}
|
||||
}
|
@ -21,6 +21,7 @@
|
||||
#define KICAD_SCHEMATIC_H
|
||||
|
||||
#include <eda_item.h>
|
||||
#include <embedded_files.h>
|
||||
#include <sch_sheet_path.h>
|
||||
#include <schematic_settings.h>
|
||||
|
||||
@ -71,7 +72,7 @@ public:
|
||||
* Right now, Eeschema can have only one schematic open at a time, but this could change.
|
||||
* Please keep this possibility in mind when adding to this object.
|
||||
*/
|
||||
class SCHEMATIC : public SCHEMATIC_IFACE, public EDA_ITEM
|
||||
class SCHEMATIC : public SCHEMATIC_IFACE, public EDA_ITEM, public EMBEDDED_FILES
|
||||
{
|
||||
public:
|
||||
SCHEMATIC( PROJECT* aPrj );
|
||||
@ -161,6 +162,9 @@ public:
|
||||
|
||||
std::vector<SCH_MARKER*> ResolveERCExclusions();
|
||||
|
||||
EMBEDDED_FILES* GetEmbeddedFiles() override;
|
||||
const EMBEDDED_FILES* GetEmbeddedFiles() const;
|
||||
|
||||
/**
|
||||
* Return a pointer to a bus alias object for the given label, or null if one
|
||||
* doesn't exist.
|
||||
@ -305,6 +309,11 @@ public:
|
||||
*/
|
||||
void RemoveAllListeners();
|
||||
|
||||
/**
|
||||
* Embed fonts in the schematic
|
||||
*/
|
||||
void EmbedFonts() override;
|
||||
|
||||
/**
|
||||
* True if a SCHEMATIC exists, false if not
|
||||
*/
|
||||
|
@ -16,6 +16,7 @@ bus_alias
|
||||
bus_entry
|
||||
cells
|
||||
center
|
||||
checksum
|
||||
circle
|
||||
clock
|
||||
clock_low
|
||||
@ -38,12 +39,15 @@ do_not_autoplace
|
||||
dot
|
||||
edge_clock_high
|
||||
effects
|
||||
embedded_fonts
|
||||
embedded_files
|
||||
end
|
||||
extends
|
||||
external
|
||||
exclude_from_sim
|
||||
face
|
||||
fields_autoplaced
|
||||
file
|
||||
fill
|
||||
font
|
||||
footprint
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include <tool/common_control.h>
|
||||
#include <tool/common_tools.h>
|
||||
#include <tool/editor_conditions.h>
|
||||
#include <tool/embed_tool.h>
|
||||
#include <tool/library_editor_control.h>
|
||||
#include <tool/picker_tool.h>
|
||||
#include <tool/properties_tool.h>
|
||||
@ -395,6 +396,7 @@ void SYMBOL_EDIT_FRAME::setupTools()
|
||||
m_toolManager->RegisterTool( new LIBRARY_EDITOR_CONTROL );
|
||||
m_toolManager->RegisterTool( new SYMBOL_EDITOR_CONTROL );
|
||||
m_toolManager->RegisterTool( new PROPERTIES_TOOL );
|
||||
m_toolManager->RegisterTool( new EMBED_TOOL );
|
||||
m_toolManager->InitTools();
|
||||
|
||||
// Run the selection tool, it is supposed to be always active
|
||||
|
@ -496,6 +496,7 @@ int EE_INSPECTION_TOOL::RunSimulation( const TOOL_EVENT& aEvent )
|
||||
int EE_INSPECTION_TOOL::ShowDatasheet( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
wxString datasheet;
|
||||
EMBEDDED_FILES* files = nullptr;
|
||||
|
||||
if( m_frame->IsType( FRAME_SCH_SYMBOL_EDITOR ) )
|
||||
{
|
||||
@ -505,6 +506,7 @@ int EE_INSPECTION_TOOL::ShowDatasheet( const TOOL_EVENT& aEvent )
|
||||
return 0;
|
||||
|
||||
datasheet = symbol->GetDatasheetField().GetText();
|
||||
files = symbol;
|
||||
}
|
||||
else if( m_frame->IsType( FRAME_SCH_VIEWER ) )
|
||||
{
|
||||
@ -514,6 +516,7 @@ int EE_INSPECTION_TOOL::ShowDatasheet( const TOOL_EVENT& aEvent )
|
||||
return 0;
|
||||
|
||||
datasheet = entry->GetDatasheetField().GetText();
|
||||
files = entry;
|
||||
}
|
||||
else if( m_frame->IsType( FRAME_SCH ) )
|
||||
{
|
||||
@ -528,6 +531,7 @@ int EE_INSPECTION_TOOL::ShowDatasheet( const TOOL_EVENT& aEvent )
|
||||
// Use GetShownText() to resolve any text variables, but don't allow adding extra text
|
||||
// (ie: the field name)
|
||||
datasheet = field->GetShownText( &symbol->Schematic()->CurrentSheet(), false );
|
||||
files = symbol->Schematic();
|
||||
}
|
||||
|
||||
if( datasheet.IsEmpty() || datasheet == wxS( "~" ) )
|
||||
@ -537,7 +541,7 @@ int EE_INSPECTION_TOOL::ShowDatasheet( const TOOL_EVENT& aEvent )
|
||||
else
|
||||
{
|
||||
GetAssociatedDocument( m_frame, datasheet, &m_frame->Prj(),
|
||||
PROJECT_SCH::SchSearchS( &m_frame->Prj() ) );
|
||||
PROJECT_SCH::SchSearchS( &m_frame->Prj() ), files );
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -200,7 +200,7 @@ int SCH_EDITOR_CONTROL::PageSetup( const TOOL_EVENT& aEvent )
|
||||
undoCmd.SetDescription( _( "Page Settings" ) );
|
||||
m_frame->SaveCopyInUndoList( undoCmd, UNDO_REDO::PAGESETTINGS, false, false );
|
||||
|
||||
DIALOG_EESCHEMA_PAGE_SETTINGS dlg( m_frame, VECTOR2I( MAX_PAGE_SIZE_EESCHEMA_MILS,
|
||||
DIALOG_EESCHEMA_PAGE_SETTINGS dlg( m_frame, m_frame->Schematic().GetEmbeddedFiles(), VECTOR2I( MAX_PAGE_SIZE_EESCHEMA_MILS,
|
||||
MAX_PAGE_SIZE_EESCHEMA_MILS ) );
|
||||
dlg.SetWksFileName( BASE_SCREEN::m_DrawingSheetFileName );
|
||||
|
||||
|
@ -87,7 +87,7 @@ void SCH_NAVIGATE_TOOL::HypertextCommand( const wxString& href )
|
||||
menu.Append( 1, wxString::Format( _( "Open %s" ), href ) );
|
||||
|
||||
if( m_frame->GetPopupMenuSelectionFromUser( menu ) == 1 )
|
||||
GetAssociatedDocument( m_frame, href, &m_frame->Prj() );
|
||||
GetAssociatedDocument( m_frame, href, &m_frame->Prj(), nullptr, &m_frame->Schematic() );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include <properties/property_mgr.h>
|
||||
#include <sch_commit.h>
|
||||
#include <sch_edit_frame.h>
|
||||
#include <symbol_edit_frame.h>
|
||||
#include <symbol_viewer_frame.h>
|
||||
#include <schematic.h>
|
||||
#include <settings/color_settings.h>
|
||||
#include <string_utils.h>
|
||||
@ -218,10 +220,31 @@ void SCH_PROPERTIES_PANEL::OnLanguageChanged( wxCommandEvent& aEvent )
|
||||
void SCH_PROPERTIES_PANEL::updateFontList()
|
||||
{
|
||||
wxPGChoices fonts;
|
||||
const std::vector<wxString>* fontFiles = nullptr;
|
||||
|
||||
if( m_frame->GetFrameType() == FRAME_SCH && m_frame->GetScreen() && m_frame->GetScreen()->Schematic() )
|
||||
{
|
||||
fontFiles = m_frame->GetScreen()->Schematic()->GetEmbeddedFiles()->GetFontFiles();
|
||||
}
|
||||
else if( m_frame->GetFrameType() == FRAME_SCH_SYMBOL_EDITOR )
|
||||
{
|
||||
SYMBOL_EDIT_FRAME* symbolFrame = static_cast<SYMBOL_EDIT_FRAME*>( m_frame );
|
||||
|
||||
if( symbolFrame->GetCurSymbol() )
|
||||
fontFiles = symbolFrame->GetCurSymbol()->GetEmbeddedFiles()->UpdateFontFiles();
|
||||
}
|
||||
else if( m_frame->GetFrameType() == FRAME_SCH_VIEWER )
|
||||
{
|
||||
SYMBOL_VIEWER_FRAME* symbolFrame = static_cast<SYMBOL_VIEWER_FRAME*>( m_frame );
|
||||
|
||||
if( symbolFrame->GetSelectedSymbol() )
|
||||
fontFiles = symbolFrame->GetSelectedSymbol()->GetEmbeddedFiles()->UpdateFontFiles();
|
||||
}
|
||||
|
||||
// Regnerate font names
|
||||
std::vector<std::string> fontNames;
|
||||
Fontconfig()->ListFonts( fontNames, std::string( Pgm().GetLanguageTag().utf8_str() ) );
|
||||
Fontconfig()->ListFonts( fontNames, std::string( Pgm().GetLanguageTag().utf8_str() ),
|
||||
fontFiles );
|
||||
|
||||
fonts.Add( _( "Default Font" ), -1 );
|
||||
fonts.Add( KICAD_FONT_NAME, -2 );
|
||||
|
43
include/dialogs/dialog_embed_files.h
Normal file
43
include/dialogs/dialog_embed_files.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 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_EMBED_FILES_H
|
||||
#define DIALOG_EMBED_FILES_H
|
||||
|
||||
#include <dialog_shim.h>
|
||||
#include <wx/panel.h>
|
||||
|
||||
|
||||
class DIALOG_EMBED_FILES : public DIALOG_SHIM
|
||||
{
|
||||
public:
|
||||
DIALOG_EMBED_FILES( wxWindow* aParent, const wxString& aTitle );
|
||||
|
||||
void InstallPanel( wxPanel* aPanel );
|
||||
|
||||
bool TransferDataToWindow() override;
|
||||
bool TransferDataFromWindow() override;
|
||||
|
||||
protected:
|
||||
wxPanel* m_contentPanel;
|
||||
};
|
||||
|
||||
|
||||
#endif //DIALOG_EMBED_FILES_H
|
@ -29,6 +29,8 @@
|
||||
class DS_DATA_MODEL;
|
||||
class EDA_DRAW_FRAME;
|
||||
class BASE_SCREEN;
|
||||
class EMBEDDED_FILES;
|
||||
class FILENAME_RESOLVER;
|
||||
|
||||
/*!
|
||||
* DIALOG_PAGES_SETTINGS class declaration
|
||||
@ -37,8 +39,8 @@ class BASE_SCREEN;
|
||||
class DIALOG_PAGES_SETTINGS: public DIALOG_PAGES_SETTINGS_BASE
|
||||
{
|
||||
public:
|
||||
DIALOG_PAGES_SETTINGS( EDA_DRAW_FRAME* aParent, double aIuPerMils,
|
||||
const VECTOR2D& aMaxUserSizeMils );
|
||||
DIALOG_PAGES_SETTINGS( EDA_DRAW_FRAME* aParent, EMBEDDED_FILES* aEmbeddedFiles,
|
||||
double aIuPerMils, const VECTOR2D& aMaxUserSizeMils );
|
||||
virtual ~DIALOG_PAGES_SETTINGS();
|
||||
|
||||
const wxString GetWksFileName()
|
||||
@ -130,7 +132,9 @@ protected:
|
||||
TITLE_BLOCK m_tb; /// Temporary title block (basic inscriptions).
|
||||
DS_DATA_MODEL* m_drawingSheet; // the alternate and temporary drawing sheet shown by the
|
||||
// dialog when the initial one is replaced by a new one
|
||||
double m_iuPerMils;
|
||||
double m_iuPerMils;
|
||||
EMBEDDED_FILES* m_embeddedFiles; // the embedded files reference from the parent
|
||||
FILENAME_RESOLVER* m_filenameResolver;
|
||||
|
||||
private:
|
||||
UNIT_BINDER m_customSizeX;
|
||||
|
@ -57,7 +57,8 @@ struct KICOMMON_API KEYWORD
|
||||
*/
|
||||
enum DSN_SYNTAX_T
|
||||
{
|
||||
DSN_NONE = -11,
|
||||
DSN_NONE = -12,
|
||||
DSN_BAR = -11, // Also called pipe '|'
|
||||
DSN_COMMENT = -10,
|
||||
DSN_STRING_QUOTE = -9,
|
||||
DSN_QUOTE_DEF = -8,
|
||||
@ -381,6 +382,13 @@ public:
|
||||
*/
|
||||
void NeedRIGHT();
|
||||
|
||||
/**
|
||||
* Call #NextTok() and then verifies that the token read in is a #DSN_BAR.
|
||||
*
|
||||
* @throw IO_ERROR if the next token is not a #DSN_BAR
|
||||
*/
|
||||
void NeedBAR();
|
||||
|
||||
/**
|
||||
* Return the C string representation of a #DSN_T value.
|
||||
*/
|
||||
|
@ -31,6 +31,8 @@
|
||||
#ifndef __INCLUDE__EDA_DOC_H__
|
||||
#define __INCLUDE__EDA_DOC_H__ 1
|
||||
|
||||
class EMBEDDED_FILES;
|
||||
|
||||
/**
|
||||
* Open a document (file) with the suitable browser.
|
||||
*
|
||||
@ -43,7 +45,7 @@
|
||||
* @param aPaths Additional paths to search for local disk datasheet files
|
||||
*/
|
||||
bool GetAssociatedDocument( wxWindow* aParent, const wxString& aDocName, PROJECT* aProject,
|
||||
SEARCH_STACK* aPaths = nullptr );
|
||||
SEARCH_STACK* aPaths = nullptr, EMBEDDED_FILES* aFiles = nullptr );
|
||||
|
||||
|
||||
#endif /* __INCLUDE__EDA_DOC_H__ */
|
||||
|
@ -52,6 +52,7 @@ enum class INSPECT_RESULT
|
||||
class UNITS_PROVIDER;
|
||||
class EDA_DRAW_FRAME;
|
||||
class MSG_PANEL_ITEM;
|
||||
class EMBEDDED_FILES;
|
||||
|
||||
namespace google { namespace protobuf { class Any; } }
|
||||
|
||||
@ -440,6 +441,8 @@ public:
|
||||
|
||||
virtual void ViewGetLayers( int aLayers[], int& aCount ) const override;
|
||||
|
||||
virtual EMBEDDED_FILES* GetEmbeddedFiles() { return nullptr; }
|
||||
|
||||
#if defined(DEBUG)
|
||||
|
||||
/**
|
||||
|
243
include/embedded_files.h
Normal file
243
include/embedded_files.h
Normal file
@ -0,0 +1,243 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 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 EMBEDDED_FILES_H
|
||||
#define EMBEDDED_FILES_H
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <wx/string.h>
|
||||
#include <wx/filename.h>
|
||||
|
||||
#include <embedded_files_lexer.h>
|
||||
#include <wildcards_and_files_ext.h>
|
||||
#include <richio.h>
|
||||
#include <picosha2.h>
|
||||
|
||||
class EMBEDDED_FILES
|
||||
{
|
||||
public:
|
||||
struct EMBEDDED_FILE
|
||||
{
|
||||
enum class FILE_TYPE
|
||||
{
|
||||
FONT,
|
||||
MODEL,
|
||||
WORKSHEET,
|
||||
DATASHEET,
|
||||
OTHER
|
||||
};
|
||||
|
||||
EMBEDDED_FILE() :
|
||||
type( FILE_TYPE::OTHER ),
|
||||
is_valid( false )
|
||||
{}
|
||||
|
||||
bool Validate()
|
||||
{
|
||||
std::string new_sha;
|
||||
picosha2::hash256_hex_string( decompressedData, new_sha );
|
||||
|
||||
is_valid = ( new_sha == data_sha );
|
||||
return is_valid;
|
||||
}
|
||||
|
||||
wxString GetLink() const
|
||||
{
|
||||
return wxString::Format( "%s://%s", FILEEXT::KiCadUriPrefix, name );
|
||||
}
|
||||
|
||||
wxString name;
|
||||
FILE_TYPE type;
|
||||
std::string compressedEncodedData;
|
||||
std::vector<char> decompressedData;
|
||||
std::string data_sha;
|
||||
bool is_valid;
|
||||
};
|
||||
|
||||
enum class RETURN_CODE : int
|
||||
{
|
||||
OK, // Success
|
||||
FILE_NOT_FOUND, // File not found on disk
|
||||
PERMISSIONS_ERROR, // Could not read/write file
|
||||
FILE_ALREADY_EXISTS, // File already exists in the collection
|
||||
OUT_OF_MEMORY, // Could not allocate memory
|
||||
CHECKSUM_ERROR, // Checksum in file does not match data
|
||||
};
|
||||
|
||||
EMBEDDED_FILES() = default;
|
||||
|
||||
~EMBEDDED_FILES()
|
||||
{
|
||||
for( auto& file : m_files )
|
||||
delete file.second;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a file from disk and adds it to the collection.
|
||||
* @param aName is the name of the file to load.
|
||||
* @param aOverwrite is true if the file should be overwritten if it already exists.
|
||||
*/
|
||||
EMBEDDED_FILE* AddFile( const wxFileName& aName, bool aOverwrite );
|
||||
|
||||
/**
|
||||
* Appends a file to the collection.
|
||||
*/
|
||||
void AddFile( EMBEDDED_FILE* aFile );
|
||||
|
||||
/**
|
||||
* Removes a file from the collection and frees the memory.
|
||||
* @param aName is the name of the file to remove.
|
||||
*/
|
||||
void RemoveFile( const wxString& name, bool aErase = true );
|
||||
|
||||
/**
|
||||
* Output formatter for the embedded files.
|
||||
* @param aOut is the output formatter.
|
||||
* @param aNestLevel is the current indentation level.
|
||||
* @param aWriteData is true if the actual data should be written. This is false when writing an element
|
||||
* that is already embedded in a file that itself has embedded files (boards, schematics, etc.)
|
||||
*/
|
||||
void WriteEmbeddedFiles( OUTPUTFORMATTER& aOut, int aNestLevel, bool aWriteData ) const;
|
||||
|
||||
/**
|
||||
* Returns the link for an embedded file.
|
||||
* @param aFile is the file to get the link for.
|
||||
* @return the link for the file to be used in a hyperlink.
|
||||
*/
|
||||
wxString GetEmbeddedFileLink( const EMBEDDED_FILE& aFile ) const
|
||||
{
|
||||
return aFile.GetLink();
|
||||
}
|
||||
|
||||
bool HasFile( const wxString& name ) const
|
||||
{
|
||||
wxFileName fileName( name );
|
||||
|
||||
return m_files.find( fileName.GetFullName() ) != m_files.end();
|
||||
}
|
||||
|
||||
bool IsEmpty() const
|
||||
{
|
||||
return m_files.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to get a list of fonts for fontconfig to add to the library.
|
||||
*
|
||||
* This is neccesary because EMBEDDED_FILES lives in common at the moment and
|
||||
* fontconfig is in libkicommon. This will create the cache files in the KiCad
|
||||
* cache directory (if they do not already exist) and return the temp files names
|
||||
*/
|
||||
const std::vector<wxString>* UpdateFontFiles();
|
||||
|
||||
/**
|
||||
* If we just need the cached version of the font files, we can use this function which
|
||||
* is const and will not update the font files.
|
||||
*/
|
||||
const std::vector<wxString>* GetFontFiles() const;
|
||||
|
||||
/**
|
||||
* Removes all embedded fonts from the collection
|
||||
*/
|
||||
void ClearEmbeddedFonts();
|
||||
|
||||
/**
|
||||
* Takes data from the #decompressedData buffer and compresses it using ZSTD
|
||||
* into the #compressedEncodedData buffer. The data is then Base64 encoded.
|
||||
*
|
||||
* This call is used when adding a new file to the collection from disk
|
||||
*/
|
||||
static RETURN_CODE CompressAndEncode( EMBEDDED_FILE& aFile );
|
||||
|
||||
/**
|
||||
* Takes data from the #compressedEncodedData buffer and Base64 decodes it.
|
||||
* The data is then decompressed using ZSTD and stored in the #decompressedData buffer.
|
||||
*
|
||||
* This call is used when loading the embedded files using the parsers.
|
||||
*/
|
||||
static RETURN_CODE DecompressAndDecode( EMBEDDED_FILE& aFile );
|
||||
|
||||
/**
|
||||
* Returns the embedded file with the given name or nullptr if it does not exist.
|
||||
*/
|
||||
EMBEDDED_FILE* GetEmbeddedFile( const wxString& aName ) const
|
||||
{
|
||||
auto it = m_files.find( aName );
|
||||
|
||||
return it == m_files.end() ? nullptr : it->second;
|
||||
}
|
||||
|
||||
const std::map<wxString, EMBEDDED_FILE*>& EmbeddedFileMap() const
|
||||
{
|
||||
return m_files;
|
||||
}
|
||||
|
||||
wxFileName GetTempFileName( const wxString& aName ) const;
|
||||
|
||||
wxFileName GetTempFileName( EMBEDDED_FILE* aFile ) const;
|
||||
|
||||
void ClearEmbeddedFiles( bool aDeleteFiles = true )
|
||||
{
|
||||
for( auto& file : m_files )
|
||||
{
|
||||
if( aDeleteFiles )
|
||||
delete file.second;
|
||||
}
|
||||
|
||||
m_files.clear();
|
||||
}
|
||||
|
||||
virtual void EmbedFonts() {};
|
||||
|
||||
void SetAreFontsEmbedded( bool aEmbedFonts )
|
||||
{
|
||||
m_embedFonts = aEmbedFonts;
|
||||
}
|
||||
|
||||
bool GetAreFontsEmbedded() const
|
||||
{
|
||||
return m_embedFonts;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool m_embedFonts; // If set, fonts will be embedded in the element on save
|
||||
// Otherwise, font files embedded in the element will be
|
||||
// removed on save
|
||||
|
||||
|
||||
private:
|
||||
std::map<wxString, EMBEDDED_FILE*> m_files;
|
||||
std::vector<wxString> m_fontFiles;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class EMBEDDED_FILES_PARSER : public EMBEDDED_FILES_LEXER
|
||||
{
|
||||
public:
|
||||
EMBEDDED_FILES_PARSER( LINE_READER* aReader ) :
|
||||
EMBEDDED_FILES_LEXER( aReader )
|
||||
{
|
||||
}
|
||||
|
||||
void ParseEmbedded( EMBEDDED_FILES* aFiles );
|
||||
|
||||
};
|
||||
#endif // EMBEDDED_FILES_H
|
@ -36,6 +36,7 @@
|
||||
|
||||
class PROJECT;
|
||||
class PGM_BASE;
|
||||
class EMBEDDED_FILES;
|
||||
|
||||
struct SEARCH_PATH
|
||||
{
|
||||
@ -99,8 +100,10 @@ public:
|
||||
*
|
||||
* @param aFileName The configured file path to resolve
|
||||
* @param aWorkingPath The current working path for relative path resolutions
|
||||
* @param aFiles The embedded files object to use for embedded file resolution
|
||||
*/
|
||||
wxString ResolvePath( const wxString& aFileName, const wxString& aWorkingPath );
|
||||
wxString ResolvePath( const wxString& aFileName, const wxString& aWorkingPath,
|
||||
const EMBEDDED_FILES* aFiles );
|
||||
|
||||
/**
|
||||
* Produce a relative path based on the existing search directories or returns the same path
|
||||
|
@ -141,7 +141,7 @@ public:
|
||||
virtual bool IsItalic() const { return false; }
|
||||
|
||||
static FONT* GetFont( const wxString& aFontName = wxEmptyString, bool aBold = false,
|
||||
bool aItalic = false );
|
||||
bool aItalic = false, const std::vector<wxString>* aEmbeddedFiles = nullptr );
|
||||
static bool IsStroke( const wxString& aFontName );
|
||||
|
||||
const wxString& GetName() const { return m_fontName; };
|
||||
|
@ -59,14 +59,18 @@ public:
|
||||
*
|
||||
* A return value of false indicates a serious error in the font system.
|
||||
*/
|
||||
FF_RESULT FindFont( const wxString& aFontName, wxString& aFontFile, int& aFaceIndex, bool aBold, bool aItalic );
|
||||
FF_RESULT FindFont( const wxString& aFontName, wxString& aFontFile, int& aFaceIndex, bool aBold,
|
||||
bool aItalic, const std::vector<wxString>* aEmbeddedFiles = nullptr );
|
||||
|
||||
/**
|
||||
* List the current available font families.
|
||||
*
|
||||
* @param aDesiredLang The desired language of font name to report back if available, otherwise it will fallback
|
||||
* @param aEmbeddedFiles A list of embedded to use for searching fonts, if nullptr, this is not used
|
||||
* @param aForce If true, force rebuilding the font cache
|
||||
*/
|
||||
void ListFonts( std::vector<std::string>& aFonts, const std::string& aDesiredLang );
|
||||
void ListFonts( std::vector<std::string>& aFonts, const std::string& aDesiredLang,
|
||||
const std::vector<wxString>* aEmbeddedFiles = nullptr, bool aForce = false );
|
||||
|
||||
/**
|
||||
* Set the reporter to use for reporting font substitution warnings.
|
||||
|
@ -36,10 +36,11 @@
|
||||
#endif
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_OUTLINE_H
|
||||
//#include <gal/opengl/opengl_freetype.h>
|
||||
|
||||
#include <font/font.h>
|
||||
#include <font/glyph.h>
|
||||
#include <font/outline_decomposer.h>
|
||||
#include <embedded_files.h>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
@ -51,6 +52,16 @@ namespace KIFONT
|
||||
class GAL_API OUTLINE_FONT : public FONT
|
||||
{
|
||||
public:
|
||||
|
||||
enum class EMBEDDING_PERMISSION
|
||||
{
|
||||
INSTALLABLE,
|
||||
EDITABLE,
|
||||
PRINT_PREVIEW_ONLY,
|
||||
RESTRICTED,
|
||||
INVALID
|
||||
};
|
||||
|
||||
OUTLINE_FONT();
|
||||
|
||||
bool IsOutline() const override { return true; }
|
||||
@ -75,11 +86,16 @@ public:
|
||||
m_fakeItal = true;
|
||||
}
|
||||
|
||||
const wxString& GetFileName() const { return m_fontFileName; }
|
||||
|
||||
EMBEDDING_PERMISSION GetEmbeddingPermission() const;
|
||||
|
||||
/**
|
||||
* Load an outline font. TrueType (.ttf) and OpenType (.otf) are supported.
|
||||
* @param aFontFileName is the (platform-specific) fully qualified name of the font file
|
||||
*/
|
||||
static OUTLINE_FONT* LoadFont( const wxString& aFontFileName, bool aBold, bool aItalic );
|
||||
static OUTLINE_FONT* LoadFont( const wxString& aFontFileName, bool aBold, bool aItalic,
|
||||
const std::vector<wxString>* aEmbeddedFiles );
|
||||
|
||||
/**
|
||||
* Compute the distance (interline) between 2 lines of text (for multiline texts). This is
|
||||
|
@ -228,6 +228,11 @@ public:
|
||||
// API
|
||||
static TOOL_ACTION pluginsReload;
|
||||
|
||||
// Embedding Files
|
||||
static TOOL_ACTION embeddedFiles;
|
||||
static TOOL_ACTION extractFile;
|
||||
static TOOL_ACTION removeFile;
|
||||
|
||||
///< Cursor control event types
|
||||
enum CURSOR_EVENT_TYPE
|
||||
{
|
||||
|
57
include/tool/embed_tool.h
Normal file
57
include/tool/embed_tool.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 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 EMBED_TOOL_H
|
||||
#define EMBED_TOOL_H
|
||||
|
||||
#include <tool/tool_interactive.h>
|
||||
|
||||
class wxFileName;
|
||||
class EMBEDDED_FILES;
|
||||
|
||||
class EMBED_TOOL : public TOOL_INTERACTIVE
|
||||
{
|
||||
public:
|
||||
EMBED_TOOL();
|
||||
|
||||
EMBED_TOOL( const std::string& aName );
|
||||
|
||||
virtual ~EMBED_TOOL() = default;
|
||||
|
||||
/// @copydoc TOOL_INTERACTIVE::Init()
|
||||
bool Init() override;
|
||||
|
||||
/// @copydoc TOOL_INTERACTIVE::Reset()
|
||||
void Reset( RESET_REASON aReason ) override;
|
||||
|
||||
int AddFile( const TOOL_EVENT& aEvent );
|
||||
|
||||
int RemoveFile( const TOOL_EVENT& aEvent );
|
||||
|
||||
std::vector<wxString> GetFileList();
|
||||
protected:
|
||||
|
||||
///< @copydoc TOOL_INTERACTIVE::setTransitions();
|
||||
void setTransitions() override;
|
||||
|
||||
private:
|
||||
EMBEDDED_FILES* m_files;
|
||||
};
|
||||
|
||||
#endif /* EMBED_TOOL_H */
|
55
include/widgets/filedlg_open_embed_file.h
Normal file
55
include/widgets/filedlg_open_embed_file.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 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 KICAD_FILEDLG_OPEN_EMBED_FILE_H
|
||||
#define KICAD_FILEDLG_OPEN_EMBED_FILE_H
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/filedlgcustomize.h>
|
||||
|
||||
|
||||
class FILEDLG_OPEN_EMBED_FILE : public wxFileDialogCustomizeHook
|
||||
{
|
||||
public:
|
||||
FILEDLG_OPEN_EMBED_FILE( bool aDefaultEmbed = true ) :
|
||||
m_embed( aDefaultEmbed )
|
||||
{};
|
||||
|
||||
virtual void AddCustomControls( wxFileDialogCustomize& customizer ) override
|
||||
{
|
||||
m_cb = customizer.AddCheckBox( _( "Embed File" ) );
|
||||
m_cb->SetValue( m_embed );
|
||||
}
|
||||
|
||||
virtual void TransferDataFromCustomControls() override
|
||||
{
|
||||
m_embed = m_cb->GetValue();
|
||||
}
|
||||
|
||||
bool GetEmbed() const { return m_embed; }
|
||||
|
||||
private:
|
||||
bool m_embed;
|
||||
|
||||
wxFileDialogCheckBox* m_cb = nullptr;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS( FILEDLG_OPEN_EMBED_FILE );
|
||||
};
|
||||
|
||||
#endif //KICAD_FILEDLG_OPEN_EMBED_FILE_H
|
@ -35,6 +35,7 @@
|
||||
class wxGrid;
|
||||
class WX_GRID;
|
||||
class DIALOG_SHIM;
|
||||
class EMBEDDED_FILES;
|
||||
|
||||
|
||||
class GRID_CELL_TEXT_BUTTON : public wxGridCellEditor
|
||||
@ -118,8 +119,9 @@ protected:
|
||||
class GRID_CELL_URL_EDITOR : public GRID_CELL_TEXT_BUTTON
|
||||
{
|
||||
public:
|
||||
GRID_CELL_URL_EDITOR( DIALOG_SHIM* aParent, SEARCH_STACK* aSearchStack = nullptr ) :
|
||||
m_dlg( aParent ), m_searchStack( aSearchStack )
|
||||
GRID_CELL_URL_EDITOR( DIALOG_SHIM* aParent, SEARCH_STACK* aSearchStack = nullptr,
|
||||
EMBEDDED_FILES* aFiles = nullptr ) :
|
||||
m_dlg( aParent ), m_searchStack( aSearchStack ), m_files( aFiles )
|
||||
{ }
|
||||
|
||||
wxGridCellEditor* Clone() const override
|
||||
@ -132,6 +134,7 @@ public:
|
||||
protected:
|
||||
DIALOG_SHIM* m_dlg;
|
||||
SEARCH_STACK* m_searchStack;
|
||||
EMBEDDED_FILES* m_files;
|
||||
};
|
||||
|
||||
|
||||
|
@ -192,6 +192,8 @@ public:
|
||||
|
||||
static const wxString GerberFileExtensionsRegex;
|
||||
|
||||
static const std::string KiCadUriPrefix;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
@ -90,7 +90,7 @@ int PL_EDITOR_CONTROL::PageSetup( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
m_frame->SaveCopyInUndoList();
|
||||
|
||||
DIALOG_PAGES_SETTINGS dlg( m_frame, drawSheetIUScale.IU_PER_MILS,
|
||||
DIALOG_PAGES_SETTINGS dlg( m_frame, nullptr, drawSheetIUScale.IU_PER_MILS,
|
||||
VECTOR2I( MAX_PAGE_SIZE_EESCHEMA_MILS,
|
||||
MAX_PAGE_SIZE_EESCHEMA_MILS ) );
|
||||
dlg.SetWksFileName( m_frame->GetCurrentFileName() );
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <connectivity/connectivity_data.h>
|
||||
#include <convert_shape_list_to_polygon.h>
|
||||
#include <footprint.h>
|
||||
#include <font/outline_font.h>
|
||||
#include <lset.h>
|
||||
#include <pcb_base_frame.h>
|
||||
#include <pcb_track.h>
|
||||
@ -82,7 +83,8 @@ BOARD::BOARD() :
|
||||
m_project( nullptr ),
|
||||
m_userUnits( EDA_UNITS::MILLIMETRES ),
|
||||
m_designSettings( new BOARD_DESIGN_SETTINGS( nullptr, "board.design_settings" ) ),
|
||||
m_NetInfo( this )
|
||||
m_NetInfo( this ),
|
||||
m_embedFonts( false )
|
||||
{
|
||||
// A too small value do not allow connecting 2 shapes (i.e. segments) not exactly connected
|
||||
// A too large value do not allow safely connecting 2 shapes like very short segments.
|
||||
@ -957,6 +959,26 @@ void BOARD::CacheTriangulation( PROGRESS_REPORTER* aReporter, const std::vector<
|
||||
}
|
||||
|
||||
|
||||
void BOARD::FixupEmbeddedData()
|
||||
{
|
||||
for( FOOTPRINT* footprint : m_footprints )
|
||||
{
|
||||
for( auto& [filename, embeddedFile] : footprint->EmbeddedFileMap() )
|
||||
{
|
||||
EMBEDDED_FILES::EMBEDDED_FILE* file = GetEmbeddedFile( filename );
|
||||
|
||||
if( file )
|
||||
{
|
||||
embeddedFile->compressedEncodedData = file->compressedEncodedData;
|
||||
embeddedFile->decompressedData = file->decompressedData;
|
||||
embeddedFile->data_sha = file->data_sha;
|
||||
embeddedFile->is_valid = file->is_valid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BOARD::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode, bool aSkipConnectivity )
|
||||
{
|
||||
if( aBoardItem == nullptr )
|
||||
@ -2498,6 +2520,56 @@ bool BOARD::GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines,
|
||||
}
|
||||
|
||||
|
||||
EMBEDDED_FILES* BOARD::GetEmbeddedFiles()
|
||||
{
|
||||
if( IsFootprintHolder() )
|
||||
return static_cast<EMBEDDED_FILES*>( GetFirstFootprint() );
|
||||
|
||||
return static_cast<EMBEDDED_FILES*>( this );
|
||||
}
|
||||
|
||||
|
||||
const EMBEDDED_FILES* BOARD::GetEmbeddedFiles() const
|
||||
{
|
||||
if( IsFootprintHolder() )
|
||||
return static_cast<const EMBEDDED_FILES*>( GetFirstFootprint() );
|
||||
|
||||
return static_cast<const EMBEDDED_FILES*>( this );
|
||||
}
|
||||
|
||||
|
||||
void BOARD::EmbedFonts()
|
||||
{
|
||||
std::set<KIFONT::OUTLINE_FONT*> fonts;
|
||||
|
||||
for( BOARD_ITEM* item : Drawings() )
|
||||
{
|
||||
if( EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( item ) )
|
||||
{
|
||||
KIFONT::FONT* font = text->GetFont();
|
||||
|
||||
if( !font || font->IsStroke() )
|
||||
continue;
|
||||
|
||||
using EMBEDDING_PERMISSION = KIFONT::OUTLINE_FONT::EMBEDDING_PERMISSION;
|
||||
auto* outline = static_cast<KIFONT::OUTLINE_FONT*>( font );
|
||||
|
||||
if( outline->GetEmbeddingPermission() == EMBEDDING_PERMISSION::EDITABLE
|
||||
|| outline->GetEmbeddingPermission() == EMBEDDING_PERMISSION::INSTALLABLE )
|
||||
{
|
||||
fonts.insert( outline );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( KIFONT::OUTLINE_FONT* font : fonts )
|
||||
{
|
||||
auto file = GetEmbeddedFiles()->AddFile( font->GetFileName(), false );
|
||||
file->type = EMBEDDED_FILES::EMBEDDED_FILE::FILE_TYPE::FONT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const std::vector<PAD*> BOARD::GetPads() const
|
||||
{
|
||||
std::vector<PAD*> allPads;
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include <board_item_container.h>
|
||||
#include <board_stackup_manager/board_stackup.h>
|
||||
#include <embedded_files.h>
|
||||
#include <common.h> // Needed for stl hash extensions
|
||||
#include <convert_shape_list_to_polygon.h> // for OUTLINE_ERROR_HANDLER
|
||||
#include <hash.h>
|
||||
@ -284,7 +285,7 @@ enum class BOARD_USE
|
||||
/**
|
||||
* Information pertinent to a Pcbnew printed circuit board.
|
||||
*/
|
||||
class BOARD : public BOARD_ITEM_CONTAINER
|
||||
class BOARD : public BOARD_ITEM_CONTAINER, public EMBEDDED_FILES
|
||||
{
|
||||
public:
|
||||
static inline bool ClassOf( const EDA_ITEM* aItem )
|
||||
@ -426,6 +427,13 @@ public:
|
||||
*/
|
||||
void FinalizeBulkRemove( std::vector<BOARD_ITEM*>& aRemovedItems );
|
||||
|
||||
/**
|
||||
* After loading a file from disk, the footprints do not yet contain the full
|
||||
* data for their embedded files, only a reference. This iterates over all footprints
|
||||
* in the board and updates them with the full embedded data.
|
||||
*/
|
||||
void FixupEmbeddedData();
|
||||
|
||||
void CacheTriangulation( PROGRESS_REPORTER* aReporter = nullptr,
|
||||
const std::vector<ZONE*>& aZones = {} );
|
||||
|
||||
@ -1246,6 +1254,14 @@ public:
|
||||
bool LegacyTeardrops() const { return m_legacyTeardrops; }
|
||||
void SetLegacyTeardrops( bool aFlag ) { m_legacyTeardrops = aFlag; }
|
||||
|
||||
EMBEDDED_FILES* GetEmbeddedFiles() override;
|
||||
const EMBEDDED_FILES* GetEmbeddedFiles() const;
|
||||
|
||||
/**
|
||||
* Finds all fonts used in the board and embeds them in the file if permissions allow
|
||||
*/
|
||||
void EmbedFonts() override;
|
||||
|
||||
// --------- Item order comparators ---------
|
||||
|
||||
struct cmp_items
|
||||
@ -1359,6 +1375,8 @@ private:
|
||||
NETINFO_LIST m_NetInfo; // net info list (name, design constraints...
|
||||
|
||||
std::vector<BOARD_LISTENER*> m_listeners;
|
||||
|
||||
bool m_embedFonts;
|
||||
};
|
||||
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <dialog_import_settings.h>
|
||||
#include <pcb_io/pcb_io.h>
|
||||
#include <pcb_io/pcb_io_mgr.h>
|
||||
#include <panel_embedded_files.h>
|
||||
#include <dialogs/panel_setup_severities.h>
|
||||
#include <dialogs/panel_setup_rules.h>
|
||||
#include <dialogs/panel_setup_teardrops.h>
|
||||
@ -203,6 +204,14 @@ DIALOG_BOARD_SETUP::DIALOG_BOARD_SETUP( PCB_EDIT_FRAME* aFrame ) :
|
||||
board->GetDesignSettings().m_DRCSeverities );
|
||||
}, _( "Violation Severity" ) );
|
||||
|
||||
m_treebook->AddPage( new wxPanel( GetTreebook() ), _( "Board Data" ) );
|
||||
m_embeddedFilesPage = m_treebook->GetPageCount();
|
||||
m_treebook->AddLazySubPage(
|
||||
[this]( wxWindow* aParent ) -> wxWindow*
|
||||
{
|
||||
return new PANEL_EMBEDDED_FILES( aParent, m_frame->GetBoard() );
|
||||
}, _( "Embedded Files" ) );
|
||||
|
||||
for( size_t i = 0; i < m_treebook->GetPageCount(); ++i )
|
||||
m_treebook->ExpandNode( i );
|
||||
|
||||
|
@ -73,6 +73,7 @@ private:
|
||||
size_t m_netclassesPage;
|
||||
size_t m_customRulesPage;
|
||||
size_t m_severitiesPage;
|
||||
size_t m_embeddedFilesPage;
|
||||
};
|
||||
|
||||
|
||||
|
@ -42,8 +42,8 @@
|
||||
#include <widgets/text_ctrl_eval.h>
|
||||
#include <widgets/std_bitmap_button.h>
|
||||
#include <settings/settings_manager.h>
|
||||
#include <panel_embedded_files.h>
|
||||
#include <panel_fp_properties_3d_model.h>
|
||||
#include <dialogs/3d_cache_dialogs.h>
|
||||
#include <dialogs/panel_preview_3d_model.h>
|
||||
#include <dialog_footprint_properties.h>
|
||||
|
||||
@ -75,6 +75,9 @@ DIALOG_FOOTPRINT_PROPERTIES::DIALOG_FOOTPRINT_PROPERTIES( PCB_EDIT_FRAME* aParen
|
||||
m_3dPanel = new PANEL_FP_PROPERTIES_3D_MODEL( m_frame, m_footprint, this, m_NoteBook );
|
||||
m_NoteBook->AddPage( m_3dPanel, _("3D Models"), false );
|
||||
|
||||
m_embeddedFiles = new PANEL_EMBEDDED_FILES( m_NoteBook, m_footprint );
|
||||
m_NoteBook->AddPage( m_embeddedFiles, _( "Embedded Files" ) );
|
||||
|
||||
// Configure display origin transforms
|
||||
m_posX.SetCoordType( ORIGIN_TRANSFORMS::ABS_X_COORD );
|
||||
m_posY.SetCoordType( ORIGIN_TRANSFORMS::ABS_Y_COORD );
|
||||
@ -261,6 +264,9 @@ bool DIALOG_FOOTPRINT_PROPERTIES::TransferDataToWindow()
|
||||
if( !m_3dPanel->TransferDataToWindow() )
|
||||
return false;
|
||||
|
||||
if( !m_embeddedFiles->TransferDataToWindow() )
|
||||
return false;
|
||||
|
||||
// Footprint Fields
|
||||
for( PCB_FIELD* srcField : m_footprint->GetFields() )
|
||||
{
|
||||
@ -494,6 +500,9 @@ bool DIALOG_FOOTPRINT_PROPERTIES::TransferDataFromWindow()
|
||||
if( !m_3dPanel->TransferDataFromWindow() )
|
||||
return false;
|
||||
|
||||
if( !m_embeddedFiles->TransferDataFromWindow() )
|
||||
return false;
|
||||
|
||||
auto view = m_frame->GetCanvas()->GetView();
|
||||
BOARD_COMMIT commit( m_frame );
|
||||
commit.Modify( m_footprint );
|
||||
|
@ -36,6 +36,7 @@
|
||||
|
||||
class PCB_EDIT_FRAME;
|
||||
class PANEL_FP_PROPERTIES_3D_MODEL;
|
||||
class PANEL_EMBEDDED_FILES;
|
||||
|
||||
class DIALOG_FOOTPRINT_PROPERTIES: public DIALOG_FOOTPRINT_PROPERTIES_BASE
|
||||
{
|
||||
@ -106,6 +107,7 @@ private:
|
||||
|
||||
wxSize m_gridSize;
|
||||
wxSize m_lastRequestedSize;
|
||||
PANEL_EMBEDDED_FILES* m_embeddedFiles;
|
||||
};
|
||||
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user