PCM implementation
|
@ -146,12 +146,17 @@ option( KICAD_GAL_PROFILE
|
|||
"Enable profiling info for GAL"
|
||||
OFF )
|
||||
|
||||
option( KICAD_PCM
|
||||
"Build Plugin and Content Manager"
|
||||
OFF )
|
||||
|
||||
cmake_dependent_option( KICAD_WIN32_INSTALL_PDBS
|
||||
"Installs debug pdb to the bin folder, DO NOT USE (NOR REQUIRED) FOR DEBUGGING THE SOURCE ON MSVC. This is purely for release building.
|
||||
MSVC can find the PDBs without this."
|
||||
OFF "WIN32"
|
||||
OFF )
|
||||
|
||||
|
||||
# Global setting: exports are explicit
|
||||
set( CMAKE_CXX_VISIBILITY_PRESET "hidden" )
|
||||
set( CMAKE_VISIBILITY_INLINES_HIDDEN ON )
|
||||
|
@ -881,7 +886,7 @@ set( wxWidgets_REQ_VERSION ${WXPYTHON_WXVERSION} )
|
|||
# See line 49 of CMakeModules/FindwxWidgets.cmake
|
||||
set( wxWidgets_CONFIG_OPTIONS ${wxWidgets_CONFIG_OPTIONS} --static=no )
|
||||
|
||||
find_package( wxWidgets ${wxWidgets_REQ_VERSION} COMPONENTS gl aui adv html core net base propgrid xml stc REQUIRED )
|
||||
find_package( wxWidgets ${wxWidgets_REQ_VERSION} COMPONENTS gl aui adv html core net base propgrid xml stc richtext REQUIRED )
|
||||
|
||||
# Include wxWidgets macros.
|
||||
include( ${wxWidgets_USE_FILE} )
|
||||
|
|
|
@ -36,6 +36,7 @@ string( REGEX MATCH
|
|||
if( CMAKE_MATCH_COUNT EQUAL 2 )
|
||||
# Match slot 0 is the full string, so we want slots 1 & 2
|
||||
set( KICAD_MAJOR_MINOR_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}" )
|
||||
set( KICAD_MAJOR_MINOR_VERSION_TUPLE "{ ${CMAKE_MATCH_1}, ${CMAKE_MATCH_2} }" )
|
||||
set( KICAD_MAJOR_VERSION "${CMAKE_MATCH_1}" )
|
||||
set( KICAD_WIN32_RC_FILEVER_STR "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.0.0\\0" )
|
||||
set( KICAD_WIN32_RC_FILEVER "${CMAKE_MATCH_1}, ${CMAKE_MATCH_2}, 0, 0" )
|
||||
|
@ -58,6 +59,7 @@ set( _wvh_new_version_text
|
|||
#define KICAD_SEMANTIC_VERSION \"${KICAD_SEMANTIC_VERSION}\"
|
||||
#define KICAD_MAJOR_VERSION \"${KICAD_MAJOR_VERSION}\"
|
||||
#define KICAD_MAJOR_MINOR_VERSION \"${KICAD_MAJOR_MINOR_VERSION}\"
|
||||
#define KICAD_MAJOR_MINOR_VERSION_TUPLE ${KICAD_MAJOR_MINOR_VERSION_TUPLE}
|
||||
#define KICAD_WIN32_RC_PRODVER ${KICAD_WIN32_RC_PRODVER}
|
||||
#define KICAD_WIN32_RC_PRODVER_STR \"${KICAD_WIN32_RC_PRODVER_STR}\"
|
||||
#define KICAD_WIN32_RC_FILEVER ${KICAD_WIN32_RC_FILEVER}
|
||||
|
|
|
@ -280,6 +280,7 @@ set( BMAPS_MID
|
|||
icon_cvpcb_24
|
||||
icon_footprint_browser
|
||||
icon_gerbview_24
|
||||
icon_pcm_24
|
||||
import3d
|
||||
image
|
||||
import_brd_file
|
||||
|
@ -529,6 +530,7 @@ set( BMAPS_BIG
|
|||
icon_bitmap2component
|
||||
icon_pagelayout_editor
|
||||
icon_pcbcalculator
|
||||
icon_pcm
|
||||
reannotate_down_left
|
||||
reannotate_down_right
|
||||
reannotate_left_down
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
|
||||
/* Do not modify this file, it was automatically generated by the
|
||||
* PNG2cpp CMake script, using a *.png file as input.
|
||||
*/
|
||||
|
||||
#include <bitmaps_png/bitmaps_list.h>
|
||||
|
||||
static const unsigned char png[] = {
|
||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
|
||||
0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x08, 0x06, 0x00, 0x00, 0x00, 0xe0, 0x77, 0x3d,
|
||||
0xf8, 0x00, 0x00, 0x03, 0x64, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0xed, 0x95, 0x5b, 0x68, 0x13,
|
||||
0x69, 0x18, 0x86, 0x83, 0x87, 0x8b, 0x15, 0xc5, 0x3b, 0xbd, 0xd8, 0x2b, 0xf1, 0x42, 0x30, 0x21,
|
||||
0xad, 0x8d, 0xa6, 0x93, 0x49, 0x67, 0xfe, 0xff, 0x9f, 0xcc, 0x24, 0x99, 0x26, 0x69, 0x26, 0x87,
|
||||
0x31, 0xa1, 0xa7, 0xb8, 0x45, 0xc4, 0x43, 0x15, 0x8a, 0xf5, 0x5c, 0xb4, 0xa5, 0xe0, 0xc6, 0x43,
|
||||
0xab, 0xa2, 0x6e, 0xd4, 0x56, 0x42, 0x77, 0xdb, 0x0a, 0x5a, 0x5b, 0x0f, 0xc8, 0xba, 0x74, 0xad,
|
||||
0x4a, 0xf1, 0x78, 0x51, 0xa5, 0x55, 0x44, 0xf0, 0x6c, 0x35, 0xb5, 0x9a, 0x63, 0x4d, 0x4a, 0x8d,
|
||||
0x9b, 0xdf, 0xa4, 0x50, 0x4d, 0x51, 0xb4, 0x6b, 0x7b, 0xa7, 0x1f, 0x3c, 0x17, 0x03, 0xf3, 0xbd,
|
||||
0x0f, 0x7c, 0x33, 0xf0, 0x4a, 0x24, 0x63, 0x98, 0x8c, 0x0c, 0xd5, 0xaf, 0x40, 0x0d, 0xaa, 0x58,
|
||||
0x80, 0x1e, 0x24, 0x79, 0x44, 0x93, 0xd0, 0x2d, 0x97, 0xd3, 0x73, 0x24, 0xe3, 0x19, 0x95, 0x4a,
|
||||
0xf5, 0x0b, 0xa1, 0xd4, 0xb8, 0x54, 0xd9, 0xf0, 0xb1, 0xcd, 0xa0, 0x79, 0xd3, 0x5c, 0x6b, 0x7d,
|
||||
0xdf, 0x77, 0xb9, 0x10, 0xbf, 0xea, 0x2c, 0xc2, 0x67, 0x0f, 0xd9, 0x12, 0xcb, 0x0a, 0x74, 0x3e,
|
||||
0x94, 0x83, 0xee, 0x93, 0x04, 0xdc, 0x20, 0x93, 0x65, 0xcf, 0x1e, 0x53, 0xa8, 0x28, 0x8a, 0x93,
|
||||
0xb3, 0xb2, 0xa0, 0x5e, 0x4d, 0x72, 0x5d, 0xa6, 0x5c, 0xa1, 0xaf, 0x6e, 0x6f, 0xc5, 0x60, 0x73,
|
||||
0x5d, 0xf5, 0x3b, 0x97, 0xd3, 0xe1, 0xcf, 0xb7, 0x99, 0x02, 0xc7, 0x6a, 0xac, 0x71, 0xdf, 0xa5,
|
||||
0x22, 0x1c, 0xbc, 0x56, 0x3c, 0x4c, 0x6f, 0x47, 0x21, 0x6e, 0xda, 0x2d, 0xc4, 0x0b, 0x2c, 0xac,
|
||||
0x8f, 0x83, 0x4c, 0x37, 0xa1, 0x84, 0x4b, 0xe7, 0xcd, 0x53, 0xcf, 0xf8, 0x2c, 0x78, 0xfe, 0x7c,
|
||||
0xb5, 0x94, 0x83, 0xa8, 0x5e, 0xcf, 0x30, 0x4f, 0xb6, 0x97, 0x1b, 0x03, 0x55, 0x6b, 0x8c, 0x51,
|
||||
0x33, 0xaf, 0x0d, 0x97, 0x97, 0xba, 0x82, 0xd7, 0xce, 0x1f, 0xc0, 0xb1, 0x67, 0xad, 0xb8, 0xb7,
|
||||
0xbb, 0x09, 0x1f, 0xde, 0xb3, 0x29, 0x66, 0x31, 0x99, 0xc3, 0xa5, 0x25, 0xe6, 0xc0, 0xbf, 0xde,
|
||||
0xc5, 0x09, 0xff, 0x95, 0x4f, 0xb2, 0x27, 0xed, 0x85, 0xd8, 0xfb, 0xbb, 0x10, 0xb3, 0xf0, 0xec,
|
||||
0x4b, 0x0e, 0xc2, 0x4e, 0x45, 0x26, 0x25, 0x28, 0x14, 0x8a, 0xa9, 0x92, 0xcc, 0x0c, 0x2a, 0x64,
|
||||
0xe1, 0x99, 0xc8, 0xb9, 0x43, 0xf6, 0x8f, 0x2f, 0x8f, 0xd0, 0xd5, 0xe2, 0xc4, 0x5b, 0xd7, 0x98,
|
||||
0x5e, 0x1b, 0xb4, 0xfa, 0xc8, 0xf6, 0x8a, 0xd2, 0xe8, 0xfd, 0xeb, 0x5e, 0x3c, 0xf8, 0xbc, 0x0d,
|
||||
0xdf, 0xbd, 0x52, 0x8f, 0x77, 0x56, 0x96, 0x05, 0x05, 0xa3, 0x31, 0x5c, 0xb1, 0x5a, 0x18, 0xb8,
|
||||
0x79, 0xdc, 0x31, 0x6a, 0xef, 0x7c, 0x9d, 0x88, 0x45, 0x93, 0x66, 0x20, 0x99, 0x1d, 0x93, 0xe8,
|
||||
0x10, 0xe8, 0xf3, 0x56, 0xa2, 0x77, 0xbf, 0xd9, 0xe0, 0x1b, 0xb3, 0x0e, 0x85, 0x3d, 0x55, 0xe6,
|
||||
0xa1, 0x87, 0xff, 0x14, 0x8c, 0x5a, 0xe8, 0x4f, 0xde, 0xfd, 0x8c, 0xc7, 0xfe, 0x5f, 0x89, 0x43,
|
||||
0x1f, 0x72, 0x08, 0xa6, 0x70, 0xa3, 0x67, 0x5b, 0xbc, 0xff, 0xde, 0x31, 0x1c, 0x7d, 0xda, 0x8a,
|
||||
0x3b, 0xda, 0x6a, 0x13, 0x2b, 0x97, 0x16, 0x07, 0xf2, 0x78, 0x3e, 0xb2, 0xca, 0x95, 0x1b, 0x15,
|
||||
0x4d, 0x6c, 0xb0, 0xc4, 0xc1, 0x05, 0x5b, 0xf7, 0x9b, 0x12, 0x46, 0x2d, 0xf2, 0x49, 0x78, 0x04,
|
||||
0x7c, 0x3d, 0xcd, 0x2c, 0x4e, 0x71, 0xc3, 0xcb, 0xe2, 0x03, 0x1b, 0x99, 0x21, 0xa7, 0x11, 0xf8,
|
||||
0xad, 0xb9, 0x4c, 0xa4, 0xc1, 0x2d, 0xc4, 0x53, 0x77, 0x4e, 0x97, 0xa5, 0x4e, 0x71, 0xa4, 0xda,
|
||||
0x32, 0x68, 0x33, 0x68, 0xc3, 0x25, 0xf9, 0xf6, 0xd0, 0x8e, 0xca, 0xb2, 0xf8, 0x92, 0xc2, 0x82,
|
||||
0xa0, 0xd3, 0x2e, 0x86, 0x38, 0xa4, 0x8f, 0x3e, 0xfc, 0xdb, 0x8e, 0x7d, 0x17, 0xc5, 0x61, 0x3e,
|
||||
0x13, 0xa4, 0x73, 0xf5, 0x28, 0x8b, 0xf7, 0xac, 0x43, 0x51, 0x41, 0x07, 0xc2, 0xc5, 0x56, 0x4d,
|
||||
0xa4, 0xb9, 0xc6, 0x92, 0x48, 0xff, 0x8b, 0x56, 0x14, 0xe9, 0xfd, 0x06, 0x16, 0x0d, 0x90, 0x04,
|
||||
0x3b, 0xf4, 0xa2, 0xa7, 0x71, 0xf8, 0x74, 0xf9, 0x76, 0x8b, 0x7f, 0x24, 0xfc, 0x9b, 0x82, 0x74,
|
||||
0x2e, 0xfc, 0xa1, 0xc1, 0x95, 0xcb, 0x61, 0x84, 0x03, 0xe0, 0xad, 0x16, 0xa1, 0xb7, 0xee, 0x72,
|
||||
0xfd, 0xc0, 0xad, 0x16, 0xeb, 0x70, 0x48, 0x1e, 0x6f, 0x88, 0xa4, 0xc2, 0xc7, 0x25, 0x18, 0xe1,
|
||||
0xe0, 0x26, 0x84, 0x1b, 0xdc, 0x46, 0x9c, 0x1e, 0x92, 0x12, 0xa4, 0xbe, 0xc5, 0xa5, 0x33, 0xfb,
|
||||
0x12, 0x56, 0x43, 0x6e, 0x68, 0xc2, 0x05, 0x1a, 0xc0, 0xc5, 0xec, 0xe6, 0xbc, 0xa0, 0x7b, 0xbd,
|
||||
0x39, 0xd4, 0xd3, 0x66, 0xc3, 0x13, 0x2e, 0xb8, 0x7d, 0xd2, 0x3a, 0xea, 0x79, 0xc2, 0x05, 0x5f,
|
||||
0xe3, 0xa7, 0xe0, 0x47, 0x11, 0xa8, 0xb3, 0xa9, 0xc0, 0xd9, 0x5a, 0xcd, 0x84, 0x0b, 0x3a, 0xff,
|
||||
0x12, 0xb0, 0x3a, 0x1b, 0x04, 0x25, 0x72, 0x39, 0x95, 0x45, 0x93, 0xf4, 0x69, 0x3d, 0xa2, 0x5e,
|
||||
0x78, 0x36, 0x33, 0x43, 0x5d, 0x7f, 0x7e, 0xbf, 0xe0, 0x59, 0xbb, 0x88, 0x1b, 0x77, 0x1a, 0xe3,
|
||||
0x79, 0x3a, 0xd4, 0xaf, 0x85, 0xb0, 0x5d, 0x2a, 0xa5, 0x94, 0x1f, 0x4b, 0x47, 0xa1, 0x60, 0x67,
|
||||
0xe6, 0x10, 0xf4, 0x16, 0x40, 0xd2, 0x4f, 0xd7, 0x2e, 0x41, 0xe1, 0x0e, 0x8f, 0x66, 0xcc, 0x82,
|
||||
0x3b, 0xa7, 0x6c, 0x78, 0xd7, 0x06, 0x3e, 0xc2, 0xd2, 0xe0, 0x25, 0x45, 0x82, 0x1a, 0xb9, 0x9c,
|
||||
0x9c, 0xf5, 0xb5, 0xe6, 0x9c, 0x94, 0x99, 0x09, 0x38, 0xa8, 0xa6, 0x2e, 0x0a, 0x3a, 0xba, 0xbf,
|
||||
0xa1, 0x0a, 0x25, 0xba, 0x9b, 0xbe, 0x2c, 0x68, 0xaf, 0x37, 0x63, 0x97, 0xc8, 0xbe, 0x06, 0x6a,
|
||||
0x78, 0x67, 0xe1, 0x02, 0xca, 0x09, 0x21, 0x9c, 0xf2, 0xbf, 0x8a, 0x5f, 0x26, 0x23, 0xe7, 0xd2,
|
||||
0x2a, 0x70, 0x98, 0xc9, 0xa1, 0x7b, 0xab, 0x4b, 0x61, 0xac, 0xb6, 0x1c, 0xe1, 0xba, 0x6a, 0x43,
|
||||
0xb2, 0x0f, 0x0c, 0x83, 0x3c, 0x83, 0xfa, 0x40, 0x0e, 0x3c, 0x21, 0x97, 0x43, 0x99, 0x64, 0xbc,
|
||||
0x93, 0xec, 0xd6, 0x69, 0x84, 0x82, 0x5a, 0x4d, 0x2c, 0xa2, 0x7d, 0x84, 0x92, 0x7e, 0x45, 0x28,
|
||||
0xa9, 0x32, 0xa9, 0x14, 0x4e, 0x1f, 0xcb, 0xee, 0x07, 0xd5, 0xc3, 0xc2, 0xa5, 0x0e, 0x15, 0xa0,
|
||||
0xc9, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82,
|
||||
};
|
||||
|
||||
const BITMAP_OPAQUE pcm_xpm[1] = {{ png, sizeof( png ), "pcm_xpm" }};
|
||||
|
||||
//EOF
|
|
@ -0,0 +1,128 @@
|
|||
|
||||
/* Do not modify this file, it was automatically generated by the
|
||||
* PNG2cpp CMake script, using a *.png file as input.
|
||||
*/
|
||||
|
||||
#include <bitmaps_png/bitmaps_list.h>
|
||||
|
||||
static const unsigned char png[] = {
|
||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
|
||||
0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x08, 0x06, 0x00, 0x00, 0x00, 0x57, 0x02, 0xf9,
|
||||
0x87, 0x00, 0x00, 0x06, 0xec, 0x49, 0x44, 0x41, 0x54, 0x68, 0xde, 0xed, 0x9a, 0x69, 0x70, 0x53,
|
||||
0x55, 0x14, 0xc7, 0x2b, 0x8e, 0x3a, 0x7e, 0x71, 0xfb, 0xa0, 0x7e, 0xd0, 0xf1, 0x03, 0xf8, 0xa1,
|
||||
0x24, 0x79, 0x69, 0x9b, 0x36, 0xa5, 0x21, 0xef, 0xbd, 0xbc, 0xbc, 0xa4, 0x4d, 0xba, 0x84, 0xb4,
|
||||
0x4d, 0xe8, 0x5e, 0x84, 0x6a, 0x5b, 0x16, 0x29, 0xd0, 0x82, 0x2c, 0x2a, 0xbb, 0x50, 0x06, 0x11,
|
||||
0x94, 0x8e, 0x2c, 0x45, 0xa0, 0x2c, 0x05, 0xca, 0x22, 0x9b, 0x45, 0xd9, 0x8b, 0x05, 0x1d, 0x28,
|
||||
0x02, 0x0a, 0xc3, 0xbe, 0x88, 0x88, 0x88, 0x80, 0x83, 0xb2, 0x68, 0xfb, 0xde, 0xf1, 0x9e, 0xfb,
|
||||
0xf2, 0x42, 0x87, 0xd2, 0x05, 0xa1, 0x35, 0x32, 0xc9, 0xcc, 0x99, 0xe4, 0x4d, 0x72, 0x73, 0xff,
|
||||
0xbf, 0x7b, 0xcf, 0x39, 0xf7, 0xe5, 0x9c, 0x84, 0x84, 0xb4, 0xc3, 0x43, 0xab, 0xe5, 0x5e, 0xd5,
|
||||
0xe9, 0xcc, 0xef, 0x84, 0xe9, 0xd9, 0xc3, 0x7a, 0x3d, 0x7b, 0x9c, 0x5c, 0x8f, 0x09, 0x0d, 0xe5,
|
||||
0x5e, 0x0f, 0x09, 0xe4, 0x47, 0x97, 0x2e, 0xd1, 0xcf, 0x10, 0xd1, 0xbd, 0x19, 0x1d, 0xbb, 0x43,
|
||||
0xa7, 0x65, 0x65, 0x9d, 0x8e, 0x95, 0x33, 0xdd, 0x36, 0x39, 0x2b, 0xc5, 0x4e, 0x5e, 0x73, 0xa0,
|
||||
0xd5, 0xb2, 0x10, 0xc6, 0xb0, 0xfb, 0x08, 0x4c, 0x91, 0x46, 0x63, 0x79, 0x39, 0x20, 0x44, 0x7b,
|
||||
0xbd, 0xde, 0xc7, 0x89, 0x68, 0x1b, 0x11, 0x57, 0xc1, 0x30, 0xec, 0x4d, 0x14, 0xe9, 0x14, 0xad,
|
||||
0x0d, 0x1f, 0x8e, 0x70, 0xc1, 0x0f, 0xeb, 0x32, 0xe0, 0xda, 0x9e, 0x5c, 0x6a, 0x27, 0xaa, 0x33,
|
||||
0x61, 0xce, 0x78, 0x37, 0xa4, 0xbb, 0xed, 0x12, 0x7e, 0x06, 0xe1, 0x88, 0xd5, 0x92, 0xb1, 0xf9,
|
||||
0x08, 0xde, 0xe1, 0xc2, 0xbb, 0x76, 0xed, 0xae, 0xd1, 0x68, 0xb8, 0xc9, 0x44, 0xf4, 0x15, 0x14,
|
||||
0x44, 0xdc, 0x44, 0xce, 0x49, 0x8d, 0x85, 0x2f, 0xcb, 0xbd, 0x7e, 0xd1, 0xcd, 0xd9, 0x81, 0xd5,
|
||||
0x19, 0x80, 0x80, 0x71, 0x56, 0x6b, 0x03, 0x8e, 0x25, 0x3b, 0xf6, 0x17, 0x79, 0x5e, 0x4f, 0x60,
|
||||
0xbc, 0xe4, 0x4b, 0x9f, 0x6c, 0x37, 0xd1, 0xaa, 0x5f, 0xeb, 0x74, 0xfc, 0x09, 0xea, 0x0e, 0x61,
|
||||
0x82, 0x54, 0x54, 0x98, 0x07, 0x25, 0x6f, 0xe7, 0x83, 0x28, 0xc4, 0x53, 0x31, 0x11, 0xe1, 0xbc,
|
||||
0x3c, 0x38, 0xcf, 0x09, 0x9b, 0x08, 0xc8, 0x95, 0xdd, 0xb9, 0xad, 0xc2, 0x7c, 0xb3, 0x2c, 0x0d,
|
||||
0xc6, 0x14, 0x25, 0x02, 0x6b, 0xb2, 0xa8, 0x30, 0xd7, 0x71, 0x37, 0x71, 0x57, 0xc9, 0x94, 0x9d,
|
||||
0x1e, 0x58, 0x74, 0x58, 0x98, 0xe5, 0x39, 0x8d, 0xc6, 0x9c, 0xcb, 0x30, 0xdc, 0x4e, 0x75, 0xeb,
|
||||
0x3d, 0x6e, 0x8f, 0xbc, 0x74, 0xce, 0x58, 0xb8, 0x72, 0x7c, 0x05, 0xdc, 0x3a, 0xbf, 0x86, 0xda,
|
||||
0xcd, 0x1f, 0x57, 0xc3, 0xee, 0xea, 0x4f, 0x60, 0x54, 0x71, 0x5f, 0x30, 0x46, 0x29, 0x2b, 0xcb,
|
||||
0x75, 0x17, 0xa4, 0x89, 0xc5, 0x89, 0x50, 0xb7, 0x32, 0xbd, 0x55, 0x10, 0x84, 0xdd, 0x59, 0xd1,
|
||||
0x13, 0x46, 0xf6, 0x4b, 0x80, 0xc8, 0x08, 0x8e, 0xba, 0x99, 0x9e, 0x61, 0x2f, 0x92, 0x45, 0x9b,
|
||||
0x41, 0xe6, 0x37, 0xdf, 0x67, 0x30, 0x3a, 0x9f, 0x22, 0x83, 0x92, 0x88, 0xd8, 0x45, 0x24, 0xf8,
|
||||
0x6e, 0xe3, 0x97, 0x39, 0x88, 0x5f, 0xc7, 0x0a, 0x02, 0xfa, 0x2d, 0x42, 0x40, 0x56, 0xcf, 0x34,
|
||||
0xb9, 0x72, 0xee, 0x38, 0xb8, 0x7c, 0x6c, 0xb9, 0x1f, 0x42, 0xb5, 0xdf, 0x4f, 0x55, 0xc1, 0xda,
|
||||
0xc5, 0x93, 0x21, 0xff, 0x8d, 0x1c, 0x0c, 0x5e, 0x19, 0xc7, 0xbb, 0x9d, 0x76, 0x69, 0xd6, 0xb8,
|
||||
0x1e, 0x70, 0x6a, 0x53, 0x56, 0xab, 0x30, 0xbf, 0xd4, 0xe4, 0xc0, 0x86, 0x59, 0x1e, 0x18, 0xd0,
|
||||
0xcb, 0x21, 0xeb, 0xf5, 0xca, 0x78, 0xe2, 0xa2, 0x47, 0x31, 0x93, 0x69, 0xb5, 0xa6, 0xce, 0xcd,
|
||||
0x0a, 0x27, 0xdb, 0x66, 0x40, 0x62, 0xe2, 0xd7, 0x57, 0x71, 0x90, 0xc5, 0x6c, 0xa9, 0xc7, 0xed,
|
||||
0xdd, 0xbb, 0xe2, 0xce, 0x0a, 0x1e, 0xdb, 0x98, 0x09, 0x33, 0x47, 0xbb, 0x80, 0xc0, 0xd0, 0x55,
|
||||
0x0e, 0x0f, 0xe3, 0xe5, 0xbe, 0x79, 0xbd, 0x60, 0xc3, 0xd2, 0x52, 0xf8, 0xe3, 0xec, 0xaa, 0x26,
|
||||
0x30, 0x97, 0x8e, 0x54, 0x02, 0xee, 0x56, 0x86, 0xb7, 0xa7, 0xcf, 0x45, 0x38, 0xe8, 0xe5, 0x8d,
|
||||
0x85, 0xca, 0x69, 0xc9, 0x70, 0x71, 0x47, 0x4e, 0xab, 0x30, 0xe7, 0xb7, 0x65, 0xd3, 0xcf, 0x92,
|
||||
0x31, 0x92, 0xba, 0x18, 0xc4, 0x1b, 0xf6, 0x63, 0x26, 0x63, 0x18, 0xd3, 0x8b, 0x3e, 0xdf, 0xc6,
|
||||
0x00, 0x62, 0xaf, 0xe1, 0x9b, 0xdd, 0xa2, 0xf8, 0x86, 0x51, 0xfd, 0xe2, 0xe9, 0x76, 0x5e, 0xdd,
|
||||
0xdd, 0x36, 0xff, 0x35, 0x45, 0x2b, 0xfe, 0x1b, 0xd3, 0xcd, 0x26, 0xbf, 0x37, 0xb4, 0x3f, 0xec,
|
||||
0xd9, 0x34, 0xb3, 0x09, 0x08, 0xda, 0xe1, 0xda, 0x72, 0x98, 0x31, 0x69, 0x98, 0x3f, 0x5e, 0x8c,
|
||||
0x91, 0xbc, 0x54, 0xfc, 0x96, 0x13, 0x36, 0x7f, 0xe6, 0x6d, 0x75, 0x2e, 0xb4, 0xa3, 0xbe, 0xc5,
|
||||
0x73, 0xc5, 0x89, 0x74, 0x3c, 0x31, 0xe2, 0x6a, 0xe6, 0xb3, 0x21, 0xbe, 0x0b, 0xc0, 0x5c, 0x8d,
|
||||
0x39, 0x7b, 0x61, 0x69, 0x32, 0x9c, 0xdb, 0xd2, 0xfa, 0x56, 0xab, 0x76, 0x69, 0x97, 0xba, 0xe5,
|
||||
0x4e, 0x49, 0xcf, 0x28, 0xab, 0x94, 0xe8, 0x74, 0xc9, 0x28, 0xf6, 0x74, 0xdd, 0xc2, 0x26, 0x20,
|
||||
0x37, 0xce, 0xad, 0xa6, 0x90, 0x08, 0x6b, 0x88, 0x10, 0xa8, 0xbf, 0xf3, 0x24, 0x5e, 0x26, 0x95,
|
||||
0x24, 0xc1, 0xa1, 0xcf, 0x33, 0x9a, 0x9d, 0x07, 0xdf, 0x9b, 0x36, 0x32, 0x09, 0x1c, 0x56, 0xab,
|
||||
0xa4, 0xea, 0xc5, 0x67, 0x0a, 0x30, 0xa4, 0x97, 0x05, 0x46, 0xf7, 0x15, 0x40, 0x34, 0x73, 0xf5,
|
||||
0x6a, 0xb0, 0xaa, 0x5b, 0xfd, 0x73, 0x1b, 0xb6, 0x5a, 0x35, 0x04, 0x5f, 0x58, 0xea, 0x86, 0x34,
|
||||
0x97, 0xdd, 0xef, 0x32, 0x24, 0x5e, 0xe0, 0xee, 0xa0, 0x57, 0xed, 0xf2, 0xb1, 0x65, 0xb0, 0x72,
|
||||
0xfe, 0x04, 0xe8, 0x9d, 0x9d, 0xe5, 0x3f, 0xec, 0x52, 0x12, 0xec, 0x12, 0x9e, 0x19, 0x67, 0x36,
|
||||
0x67, 0xf9, 0xbf, 0x0f, 0xcf, 0x0f, 0x8c, 0x3d, 0x25, 0x9e, 0x44, 0xa9, 0x6c, 0x74, 0x02, 0x8c,
|
||||
0x2d, 0x72, 0xdc, 0x01, 0x40, 0xf1, 0xdf, 0x2f, 0xb5, 0x51, 0xfb, 0x62, 0x86, 0x48, 0xaf, 0x79,
|
||||
0x93, 0x02, 0x13, 0x1e, 0xc6, 0xc9, 0xf9, 0x99, 0x71, 0xb0, 0x7a, 0x66, 0x2a, 0xfc, 0xba, 0xab,
|
||||
0xed, 0x30, 0xfb, 0xaa, 0xd2, 0x61, 0xc2, 0x90, 0x04, 0x7f, 0x8a, 0x8c, 0x34, 0x08, 0xf2, 0xf0,
|
||||
0xc1, 0x05, 0x50, 0xb3, 0xfe, 0x63, 0xba, 0x0b, 0x77, 0xc3, 0x9c, 0xde, 0xb7, 0x10, 0x66, 0x4e,
|
||||
0x19, 0x0e, 0x0e, 0x7b, 0x92, 0x7a, 0xd8, 0xd1, 0x85, 0xc4, 0xd7, 0xf1, 0x36, 0x41, 0x2a, 0x1d,
|
||||
0xea, 0x84, 0xba, 0x2a, 0x12, 0x3b, 0xdb, 0xbd, 0xd4, 0xf0, 0xfa, 0x9e, 0x00, 0xaa, 0x1d, 0x5c,
|
||||
0x22, 0x42, 0x55, 0xa9, 0x15, 0x4a, 0x7a, 0x5b, 0x20, 0xc6, 0xc8, 0x51, 0x11, 0xd1, 0x91, 0x1c,
|
||||
0xf5, 0x5b, 0x74, 0x99, 0xb6, 0xe4, 0x79, 0x35, 0x45, 0x6e, 0x9a, 0xeb, 0x81, 0xa2, 0xde, 0x0e,
|
||||
0x99, 0x2c, 0x06, 0x15, 0x67, 0xe5, 0x9d, 0xf2, 0xd4, 0xf1, 0xc5, 0x70, 0xa4, 0x76, 0x9e, 0xdf,
|
||||
0xad, 0x76, 0xae, 0x9b, 0x0e, 0xc3, 0x8a, 0x0a, 0x08, 0xa8, 0xe2, 0x22, 0x24, 0x03, 0x61, 0x22,
|
||||
0x81, 0xcd, 0xe5, 0x3d, 0xfc, 0xa2, 0x1b, 0x5b, 0xab, 0x00, 0x8d, 0xed, 0xd0, 0x12, 0x1b, 0x54,
|
||||
0x7e, 0x60, 0x85, 0xc2, 0x74, 0x5e, 0x36, 0x84, 0xb3, 0x74, 0x02, 0xce, 0x24, 0x48, 0x18, 0xc4,
|
||||
0x6d, 0x09, 0x78, 0xd5, 0x7e, 0x22, 0x59, 0xa5, 0x62, 0x4a, 0x32, 0x64, 0x34, 0x72, 0x09, 0xce,
|
||||
0x1c, 0x0b, 0x46, 0xa3, 0x48, 0x57, 0xda, 0x18, 0x25, 0x4a, 0x08, 0x81, 0x30, 0x03, 0x0b, 0xfa,
|
||||
0x40, 0x56, 0xb2, 0x78, 0x4f, 0xf1, 0xf7, 0x0d, 0xd0, 0xd8, 0xea, 0x2a, 0x6c, 0xb0, 0x60, 0xac,
|
||||
0x00, 0x79, 0x1e, 0x5e, 0x26, 0x87, 0x0d, 0x9d, 0x58, 0xe4, 0x94, 0x20, 0x3c, 0xd8, 0x42, 0x10,
|
||||
0xaa, 0xf6, 0xdd, 0x2a, 0xe5, 0x56, 0x42, 0x64, 0x95, 0x00, 0xa6, 0x3b, 0x6b, 0x14, 0x69, 0x2a,
|
||||
0xbe, 0x7e, 0x66, 0xa5, 0xdf, 0xa5, 0x06, 0x16, 0xb6, 0x13, 0x40, 0x63, 0xfb, 0x76, 0xbe, 0x0d,
|
||||
0xca, 0x46, 0x08, 0x90, 0xe3, 0xe6, 0x25, 0xc6, 0xe7, 0xaf, 0x89, 0x76, 0x51, 0x42, 0x81, 0x47,
|
||||
0xd6, 0x67, 0xb6, 0x70, 0x33, 0xc7, 0x41, 0x5a, 0x92, 0x55, 0x9e, 0x37, 0x31, 0x01, 0xd2, 0x7b,
|
||||
0x88, 0xe0, 0x4e, 0x4c, 0x6e, 0x12, 0x13, 0x1d, 0x02, 0xd0, 0xd8, 0x6a, 0xe6, 0x88, 0x30, 0x65,
|
||||
0xb0, 0x00, 0x3d, 0x62, 0xf9, 0x06, 0x55, 0x24, 0xc9, 0x18, 0x72, 0xb2, 0x53, 0xa4, 0xd9, 0x48,
|
||||
0xc9, 0x30, 0xd6, 0x06, 0xcc, 0x20, 0x87, 0xd7, 0xa6, 0xfa, 0x85, 0xa0, 0xc8, 0x80, 0x00, 0x68,
|
||||
0x6c, 0x5b, 0xca, 0x44, 0x18, 0xd7, 0xdf, 0x42, 0x6e, 0xee, 0x58, 0x39, 0x22, 0x9c, 0x93, 0x71,
|
||||
0xb2, 0xbd, 0xcb, 0x53, 0xee, 0x29, 0x24, 0x20, 0x01, 0x54, 0xeb, 0x99, 0xc0, 0xb7, 0x28, 0xe2,
|
||||
0x91, 0x03, 0xb8, 0x76, 0x72, 0x05, 0xac, 0xa9, 0x98, 0x04, 0x79, 0xb9, 0xd9, 0xf4, 0x46, 0xb0,
|
||||
0x20, 0xcb, 0xfe, 0xff, 0x00, 0x10, 0xf8, 0x78, 0x18, 0x3e, 0xa8, 0x10, 0xa2, 0x22, 0x45, 0x1a,
|
||||
0xe4, 0x9e, 0x04, 0xf1, 0xef, 0xf2, 0x09, 0x89, 0x70, 0xb2, 0x3a, 0x35, 0xf0, 0x01, 0x72, 0x52,
|
||||
0x44, 0xf0, 0xfd, 0x7e, 0xa8, 0x9f, 0x38, 0xc4, 0x41, 0x62, 0x25, 0xb9, 0xc5, 0xcf, 0x07, 0x1c,
|
||||
0x00, 0x9e, 0xb4, 0xeb, 0xca, 0x5c, 0x70, 0x61, 0x9b, 0xb7, 0x4d, 0xc2, 0x03, 0x0e, 0xe0, 0xdf,
|
||||
0x5a, 0x10, 0x20, 0x08, 0x10, 0x04, 0x08, 0x02, 0x04, 0x01, 0x82, 0x00, 0x41, 0x80, 0x20, 0x40,
|
||||
0x10, 0xe0, 0x11, 0x01, 0xb8, 0x15, 0xae, 0x67, 0xa5, 0xa2, 0x1c, 0x0b, 0x6c, 0xf8, 0xc8, 0x1a,
|
||||
0xf0, 0x00, 0x5f, 0x2f, 0x76, 0xc3, 0xb0, 0x82, 0x38, 0xf0, 0x15, 0xc9, 0x1a, 0x10, 0x80, 0xd1,
|
||||
0x6a, 0xb9, 0x79, 0xe4, 0x99, 0xf6, 0x02, 0x52, 0x9d, 0xbc, 0x34, 0xfb, 0x5d, 0x2b, 0x1c, 0x58,
|
||||
0x1c, 0x38, 0x00, 0xe7, 0xb7, 0x78, 0x60, 0xe9, 0xd4, 0x24, 0x48, 0x73, 0x29, 0x05, 0x30, 0xf2,
|
||||
0x73, 0xb3, 0x5e, 0xa3, 0x31, 0x2f, 0xd1, 0x68, 0x58, 0xa3, 0xbf, 0x3f, 0x60, 0x30, 0xd8, 0x9e,
|
||||
0xc5, 0xa6, 0x9b, 0x9e, 0xc1, 0xb6, 0x28, 0x0b, 0x26, 0x23, 0xdb, 0x30, 0xe2, 0x4d, 0x01, 0xb6,
|
||||
0x7f, 0x2a, 0xfe, 0x67, 0x00, 0x58, 0x7e, 0x99, 0x3e, 0xca, 0x89, 0x25, 0xc6, 0x06, 0x5f, 0xd7,
|
||||
0xe6, 0x92, 0xd2, 0x9b, 0xb3, 0xbc, 0xd2, 0x52, 0x93, 0xa6, 0x13, 0xf6, 0xa8, 0x74, 0x1a, 0xb6,
|
||||
0x4a, 0xab, 0x35, 0x4b, 0xd8, 0x32, 0xcd, 0x75, 0xf3, 0xb4, 0xb4, 0x88, 0x25, 0xc6, 0x8e, 0x00,
|
||||
0xa8, 0xa9, 0x70, 0xc3, 0xa0, 0x3e, 0xb1, 0xa0, 0x56, 0xfe, 0x74, 0x3a, 0xb6, 0x0e, 0x5b, 0x5d,
|
||||
0x06, 0x83, 0xe1, 0x89, 0xfb, 0x6c, 0xec, 0x99, 0x3a, 0xfb, 0xba, 0x91, 0xb4, 0x01, 0x62, 0x63,
|
||||
0x39, 0x09, 0x8b, 0x57, 0x7b, 0x17, 0x3c, 0x7c, 0x80, 0x73, 0x5f, 0x79, 0xa0, 0xa2, 0x34, 0x11,
|
||||
0x5c, 0x71, 0x4a, 0x71, 0x97, 0x61, 0xb8, 0x3f, 0xc9, 0xdc, 0xb3, 0x89, 0xbb, 0xe8, 0x1e, 0x42,
|
||||
0x13, 0x9b, 0xf6, 0xcd, 0x72, 0xf5, 0x7a, 0xf6, 0x00, 0x2d, 0x95, 0x47, 0xb0, 0xd2, 0xc0, 0x6c,
|
||||
0x0b, 0x2d, 0xc5, 0x3f, 0x28, 0xc0, 0xbe, 0x15, 0x29, 0x30, 0x7e, 0x90, 0x13, 0xba, 0x19, 0x95,
|
||||
0x8a, 0x1e, 0x59, 0xac, 0x53, 0x4a, 0x37, 0xd4, 0xfc, 0x7c, 0xbb, 0xb4, 0x5b, 0xb1, 0x97, 0x46,
|
||||
0x57, 0x46, 0xab, 0x34, 0x00, 0x53, 0x1c, 0x9c, 0x5c, 0xfe, 0xbe, 0x00, 0x07, 0x17, 0xb7, 0x1d,
|
||||
0xe0, 0xc2, 0x56, 0x0f, 0x6c, 0x9c, 0xe5, 0x82, 0xbc, 0x34, 0x9b, 0xd2, 0x38, 0xd4, 0x52, 0x57,
|
||||
0xd9, 0x8c, 0xcd, 0x45, 0x32, 0xc5, 0x63, 0x1d, 0xd2, 0xec, 0xd6, 0x6a, 0xa3, 0x5f, 0xc2, 0x95,
|
||||
0xd2, 0x33, 0xdc, 0x79, 0x04, 0x31, 0x47, 0xb3, 0x12, 0x9e, 0x27, 0xb5, 0xe5, 0xcd, 0x03, 0x9c,
|
||||
0xac, 0xf6, 0x00, 0xd6, 0x46, 0x45, 0x96, 0x57, 0x8b, 0xbc, 0xbf, 0xa1, 0x8b, 0x86, 0x86, 0x9a,
|
||||
0x5e, 0xfb, 0x2f, 0xff, 0x71, 0xd0, 0x49, 0x69, 0xcb, 0x72, 0x5b, 0x89, 0x28, 0x59, 0xcf, 0x98,
|
||||
0xa5, 0x3c, 0x8f, 0x05, 0x56, 0x4e, 0xb1, 0xfa, 0x01, 0x76, 0x2d, 0x22, 0xb9, 0x3b, 0xdf, 0x9f,
|
||||
0xbb, 0xb1, 0xd8, 0xbb, 0x1f, 0x33, 0x5e, 0x4c, 0x4c, 0xcc, 0xd3, 0x01, 0xf5, 0x87, 0x0f, 0x92,
|
||||
0x97, 0xbb, 0x92, 0x33, 0xa5, 0x8c, 0xf8, 0xf1, 0x0d, 0x14, 0x1a, 0x15, 0xc1, 0xc9, 0xc6, 0x48,
|
||||
0x5e, 0xcd, 0xdd, 0xb7, 0xf1, 0xbc, 0x21, 0xef, 0x45, 0x84, 0x04, 0xfa, 0x43, 0xf9, 0xe7, 0x0a,
|
||||
0x3b, 0xc0, 0xd7, 0xbe, 0xbd, 0x4e, 0x84, 0x97, 0x68, 0x34, 0x31, 0x2f, 0xb4, 0xc7, 0x5c, 0xff,
|
||||
0x00, 0x9f, 0xf5, 0x05, 0x14, 0xf5, 0x92, 0x8b, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e,
|
||||
0x44, 0xae, 0x42, 0x60, 0x82,
|
||||
};
|
||||
|
||||
const BITMAP_OPAQUE icon_pcm_xpm[1] = {{ png, sizeof( png ), "icon_pcm_xpm" }};
|
||||
|
||||
//EOF
|
After Width: | Height: | Size: 101 KiB |
|
@ -20,7 +20,8 @@ ICON_FILES="icon_3d.svg
|
|||
icon_pl_editor.svg
|
||||
icon_cvpcb.svg
|
||||
icon_pcbnew.svg
|
||||
icon_eeschema.svg"
|
||||
icon_eeschema.svg
|
||||
icon_pcm.svg"
|
||||
|
||||
# convert .svg files into .png files
|
||||
for fl in $ICON_FILES
|
||||
|
|
After Width: | Height: | Size: 925 B |
After Width: | Height: | Size: 925 B |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 1.8 KiB |
|
@ -0,0 +1,67 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
|
||||
<g id="XMLID_9_">
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#E7BF55" points="63,12 63,50 32,63 32,23 43.6,18.9 44,19 44,29 52,26 52,16 51.9,15.9 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#EFC75E" points="63,12 51.9,15.9 22,5 21.9,4.7 32,1 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#F7E3AF" points="52,16 52,26 44,29 44,19 43.6,18.9 51.9,15.9 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#F7E3AF" points="51.9,15.9 43.6,18.9 14,8 13.9,7.6 21.9,4.7 22,5 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#EFC75E" points="43.6,18.9 32,23 1,12.2 13.9,7.6 14,8 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#D3A644" points="32,23 32,63 1,50 1,12.2 "/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#2C2C3D" d="M32,24c-0.1,0-0.2,0-0.3-0.1l-31-10.8c-0.5-0.2-0.8-0.8-0.6-1.3s0.8-0.8,1.3-0.6L32,21.9l30.7-10.9
|
||||
c0.5-0.2,1.1,0.1,1.3,0.6c0.2,0.5-0.1,1.1-0.6,1.3l-31,11C32.2,24,32.1,24,32,24z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#2C2C3D" d="M32,64c-0.1,0-0.3,0-0.4-0.1l-31-13C0.2,50.8,0,50.4,0,50V12.2c0-0.4,0.3-0.8,0.7-0.9l31-11.2
|
||||
c0.2-0.1,0.5-0.1,0.7,0l31,11c0.4,0.1,0.7,0.5,0.7,0.9v38c0,0.4-0.2,0.8-0.6,0.9l-31,13C32.3,64,32.1,64,32,64z M2,49.3l30,12.6
|
||||
l30-12.6V12.7L32,2.1L2,12.9V49.3z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#2C2C3D" d="M32,64c-0.6,0-1-0.4-1-1V23c0-0.6,0.4-1,1-1s1,0.4,1,1v40C33,63.6,32.6,64,32,64z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#2C2C3D" d="M44,30c-0.2,0-0.4-0.1-0.6-0.2C43.2,29.6,43,29.3,43,29v-9.3L13.7,8.9c-0.5-0.2-0.8-0.8-0.6-1.3
|
||||
c0.2-0.5,0.8-0.8,1.3-0.6l30,11c0.4,0.1,0.7,0.5,0.7,0.9v8.6l6-2.2v-8.6L21.7,5.9c-0.5-0.2-0.8-0.8-0.6-1.3
|
||||
c0.2-0.5,0.8-0.8,1.3-0.6l30,11c0.4,0.1,0.6,0.5,0.6,0.9v10c0,0.4-0.3,0.8-0.6,0.9l-8,3C44.2,30,44.1,30,44,30z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
|
@ -0,0 +1,67 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
|
||||
<g id="XMLID_9_">
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#E7BF55" points="63,12 63,50 32,63 32,23 43.6,18.9 44,19 44,29 52,26 52,16 51.9,15.9 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#EFC75E" points="63,12 51.9,15.9 22,5 21.9,4.7 32,1 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#F7E3AF" points="52,16 52,26 44,29 44,19 43.6,18.9 51.9,15.9 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#F7E3AF" points="51.9,15.9 43.6,18.9 14,8 13.9,7.6 21.9,4.7 22,5 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#EFC75E" points="43.6,18.9 32,23 1,12.2 13.9,7.6 14,8 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#D3A644" points="32,23 32,63 1,50 1,12.2 "/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#2C2C3D" d="M32,24c-0.1,0-0.2,0-0.3-0.1l-31-10.8c-0.5-0.2-0.8-0.8-0.6-1.3s0.8-0.8,1.3-0.6L32,21.9l30.7-10.9
|
||||
c0.5-0.2,1.1,0.1,1.3,0.6c0.2,0.5-0.1,1.1-0.6,1.3l-31,11C32.2,24,32.1,24,32,24z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#2C2C3D" d="M32,64c-0.1,0-0.3,0-0.4-0.1l-31-13C0.2,50.8,0,50.4,0,50V12.2c0-0.4,0.3-0.8,0.7-0.9l31-11.2
|
||||
c0.2-0.1,0.5-0.1,0.7,0l31,11c0.4,0.1,0.7,0.5,0.7,0.9v38c0,0.4-0.2,0.8-0.6,0.9l-31,13C32.3,64,32.1,64,32,64z M2,49.3l30,12.6
|
||||
l30-12.6V12.7L32,2.1L2,12.9V49.3z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#2C2C3D" d="M32,64c-0.6,0-1-0.4-1-1V23c0-0.6,0.4-1,1-1s1,0.4,1,1v40C33,63.6,32.6,64,32,64z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#2C2C3D" d="M44,30c-0.2,0-0.4-0.1-0.6-0.2C43.2,29.6,43,29.3,43,29v-9.3L13.7,8.9c-0.5-0.2-0.8-0.8-0.6-1.3
|
||||
c0.2-0.5,0.8-0.8,1.3-0.6l30,11c0.4,0.1,0.7,0.5,0.7,0.9v8.6l6-2.2v-8.6L21.7,5.9c-0.5-0.2-0.8-0.8-0.6-1.3
|
||||
c0.2-0.5,0.8-0.8,1.3-0.6l30,11c0.4,0.1,0.6,0.5,0.6,0.9v10c0,0.4-0.3,0.8-0.6,0.9l-8,3C44.2,30,44.1,30,44,30z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
|
@ -0,0 +1,67 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
|
||||
<g id="XMLID_9_">
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#E7BF55" points="63,12 63,50 32,63 32,23 43.6,18.9 44,19 44,29 52,26 52,16 51.9,15.9 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#EFC75E" points="63,12 51.9,15.9 22,5 21.9,4.7 32,1 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#F7E3AF" points="52,16 52,26 44,29 44,19 43.6,18.9 51.9,15.9 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#F7E3AF" points="51.9,15.9 43.6,18.9 14,8 13.9,7.6 21.9,4.7 22,5 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#EFC75E" points="43.6,18.9 32,23 1,12.2 13.9,7.6 14,8 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#D3A644" points="32,23 32,63 1,50 1,12.2 "/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#2C2C3D" d="M32,24c-0.1,0-0.2,0-0.3-0.1l-31-10.8c-0.5-0.2-0.8-0.8-0.6-1.3s0.8-0.8,1.3-0.6L32,21.9l30.7-10.9
|
||||
c0.5-0.2,1.1,0.1,1.3,0.6c0.2,0.5-0.1,1.1-0.6,1.3l-31,11C32.2,24,32.1,24,32,24z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#2C2C3D" d="M32,64c-0.1,0-0.3,0-0.4-0.1l-31-13C0.2,50.8,0,50.4,0,50V12.2c0-0.4,0.3-0.8,0.7-0.9l31-11.2
|
||||
c0.2-0.1,0.5-0.1,0.7,0l31,11c0.4,0.1,0.7,0.5,0.7,0.9v38c0,0.4-0.2,0.8-0.6,0.9l-31,13C32.3,64,32.1,64,32,64z M2,49.3l30,12.6
|
||||
l30-12.6V12.7L32,2.1L2,12.9V49.3z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#2C2C3D" d="M32,64c-0.6,0-1-0.4-1-1V23c0-0.6,0.4-1,1-1s1,0.4,1,1v40C33,63.6,32.6,64,32,64z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#2C2C3D" d="M44,30c-0.2,0-0.4-0.1-0.6-0.2C43.2,29.6,43,29.3,43,29v-9.3L13.7,8.9c-0.5-0.2-0.8-0.8-0.6-1.3
|
||||
c0.2-0.5,0.8-0.8,1.3-0.6l30,11c0.4,0.1,0.7,0.5,0.7,0.9v8.6l6-2.2v-8.6L21.7,5.9c-0.5-0.2-0.8-0.8-0.6-1.3
|
||||
c0.2-0.5,0.8-0.8,1.3-0.6l30,11c0.4,0.1,0.6,0.5,0.6,0.9v10c0,0.4-0.3,0.8-0.6,0.9l-8,3C44.2,30,44.1,30,44,30z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
|
@ -0,0 +1,67 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
|
||||
<g id="XMLID_9_">
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#E7BF55" points="63,12 63,50 32,63 32,23 43.6,18.9 44,19 44,29 52,26 52,16 51.9,15.9 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#EFC75E" points="63,12 51.9,15.9 22,5 21.9,4.7 32,1 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#F7E3AF" points="52,16 52,26 44,29 44,19 43.6,18.9 51.9,15.9 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#F7E3AF" points="51.9,15.9 43.6,18.9 14,8 13.9,7.6 21.9,4.7 22,5 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#EFC75E" points="43.6,18.9 32,23 1,12.2 13.9,7.6 14,8 "/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<polygon fill="#D3A644" points="32,23 32,63 1,50 1,12.2 "/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#2C2C3D" d="M32,24c-0.1,0-0.2,0-0.3-0.1l-31-10.8c-0.5-0.2-0.8-0.8-0.6-1.3s0.8-0.8,1.3-0.6L32,21.9l30.7-10.9
|
||||
c0.5-0.2,1.1,0.1,1.3,0.6c0.2,0.5-0.1,1.1-0.6,1.3l-31,11C32.2,24,32.1,24,32,24z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#2C2C3D" d="M32,64c-0.1,0-0.3,0-0.4-0.1l-31-13C0.2,50.8,0,50.4,0,50V12.2c0-0.4,0.3-0.8,0.7-0.9l31-11.2
|
||||
c0.2-0.1,0.5-0.1,0.7,0l31,11c0.4,0.1,0.7,0.5,0.7,0.9v38c0,0.4-0.2,0.8-0.6,0.9l-31,13C32.3,64,32.1,64,32,64z M2,49.3l30,12.6
|
||||
l30-12.6V12.7L32,2.1L2,12.9V49.3z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#2C2C3D" d="M32,64c-0.6,0-1-0.4-1-1V23c0-0.6,0.4-1,1-1s1,0.4,1,1v40C33,63.6,32.6,64,32,64z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#2C2C3D" d="M44,30c-0.2,0-0.4-0.1-0.6-0.2C43.2,29.6,43,29.3,43,29v-9.3L13.7,8.9c-0.5-0.2-0.8-0.8-0.6-1.3
|
||||
c0.2-0.5,0.8-0.8,1.3-0.6l30,11c0.4,0.1,0.7,0.5,0.7,0.9v8.6l6-2.2v-8.6L21.7,5.9c-0.5-0.2-0.8-0.8-0.6-1.3
|
||||
c0.2-0.5,0.8-0.8,1.3-0.6l30,11c0.4,0.1,0.6,0.5,0.6,0.9v10c0,0.4-0.3,0.8-0.6,0.9l-8,3C44.2,30,44.1,30,44,30z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
|
@ -22,7 +22,6 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <kicad_curl/kicad_curl.h>
|
||||
#include <kicad_curl/kicad_curl_easy.h>
|
||||
|
||||
#include <cstdarg>
|
||||
|
@ -37,6 +36,19 @@
|
|||
#include <pgm_base.h>
|
||||
|
||||
|
||||
struct CURL_PROGRESS
|
||||
{
|
||||
KICAD_CURL_EASY* curl;
|
||||
TRANSFER_CALLBACK callback;
|
||||
curl_off_t last_run_time;
|
||||
curl_off_t interval;
|
||||
CURL_PROGRESS( KICAD_CURL_EASY* c, TRANSFER_CALLBACK cb, curl_off_t i ) :
|
||||
curl( c ), callback( cb ), last_run_time( 0 ), interval( i )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static size_t write_callback( void* contents, size_t size, size_t nmemb, void* userp )
|
||||
{
|
||||
size_t realsize = size * nmemb;
|
||||
|
@ -48,9 +60,19 @@ static size_t write_callback( void* contents, size_t size, size_t nmemb, void* u
|
|||
return realsize;
|
||||
}
|
||||
|
||||
static size_t stream_write_callback( void* contents, size_t size, size_t nmemb, void* userp )
|
||||
{
|
||||
size_t realsize = size * nmemb;
|
||||
|
||||
KICAD_CURL_EASY::KICAD_CURL_EASY() :
|
||||
m_headers( nullptr )
|
||||
std::ostream* p = (std::ostream*) userp;
|
||||
|
||||
p->write( (const char*) contents, realsize );
|
||||
|
||||
return realsize;
|
||||
}
|
||||
|
||||
|
||||
KICAD_CURL_EASY::KICAD_CURL_EASY() : m_headers( nullptr )
|
||||
{
|
||||
// Call KICAD_CURL::Init() from in here everytime, but only the first time
|
||||
// will incur any overhead. This strategy ensures that libcurl is never loaded
|
||||
|
@ -89,6 +111,7 @@ KICAD_CURL_EASY::KICAD_CURL_EASY() :
|
|||
|
||||
user_agent << "/" << GetBuildDate();
|
||||
setOption<const char*>( CURLOPT_USERAGENT, user_agent.ToStdString().c_str() );
|
||||
setOption( CURLOPT_ACCEPT_ENCODING, "gzip,deflate" );
|
||||
}
|
||||
|
||||
|
||||
|
@ -101,7 +124,7 @@ KICAD_CURL_EASY::~KICAD_CURL_EASY()
|
|||
}
|
||||
|
||||
|
||||
void KICAD_CURL_EASY::Perform()
|
||||
int KICAD_CURL_EASY::Perform()
|
||||
{
|
||||
if( m_headers )
|
||||
{
|
||||
|
@ -113,12 +136,7 @@ void KICAD_CURL_EASY::Perform()
|
|||
|
||||
CURLcode res = curl_easy_perform( m_CURL );
|
||||
|
||||
if( res != CURLE_OK )
|
||||
{
|
||||
std::string msg = "curl_easy_perform()=";
|
||||
msg += (int)res; msg += " "; msg += GetErrorText( res ).c_str();
|
||||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
@ -129,15 +147,16 @@ void KICAD_CURL_EASY::SetHeader( const std::string& aName, const std::string& aV
|
|||
}
|
||||
|
||||
|
||||
template <typename T> int KICAD_CURL_EASY::setOption( int aOption, T aArg )
|
||||
template <typename T>
|
||||
int KICAD_CURL_EASY::setOption( int aOption, T aArg )
|
||||
{
|
||||
return curl_easy_setopt( m_CURL, (CURLoption)aOption, aArg );
|
||||
return curl_easy_setopt( m_CURL, (CURLoption) aOption, aArg );
|
||||
}
|
||||
|
||||
|
||||
const std::string KICAD_CURL_EASY::GetErrorText( int aCode )
|
||||
{
|
||||
return curl_easy_strerror( (CURLcode)aCode );
|
||||
return curl_easy_strerror( (CURLcode) aCode );
|
||||
}
|
||||
|
||||
|
||||
|
@ -154,7 +173,7 @@ bool KICAD_CURL_EASY::SetUserAgent( const std::string& aAgent )
|
|||
|
||||
bool KICAD_CURL_EASY::SetURL( const std::string& aURL )
|
||||
{
|
||||
if( setOption<const char *>( CURLOPT_URL, aURL.c_str() ) == CURLE_OK )
|
||||
if( setOption<const char*>( CURLOPT_URL, aURL.c_str() ) == CURLE_OK )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -165,7 +184,7 @@ bool KICAD_CURL_EASY::SetURL( const std::string& aURL )
|
|||
|
||||
bool KICAD_CURL_EASY::SetFollowRedirects( bool aFollow )
|
||||
{
|
||||
if( setOption<long>( CURLOPT_FOLLOWLOCATION , (aFollow ? 1 : 0) ) == CURLE_OK )
|
||||
if( setOption<long>( CURLOPT_FOLLOWLOCATION, ( aFollow ? 1 : 0 ) ) == CURLE_OK )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -183,3 +202,48 @@ std::string KICAD_CURL_EASY::Escape( const std::string& aUrl )
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int KICAD_CURL_EASY::xferinfo( void* p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal,
|
||||
curl_off_t ulnow )
|
||||
{
|
||||
CURL_PROGRESS* progress = (CURL_PROGRESS*) p;
|
||||
curl_off_t curtime = 0;
|
||||
|
||||
curl_easy_getinfo( progress->curl->m_CURL, CURLINFO_TOTAL_TIME_T, &curtime );
|
||||
|
||||
if( curtime - progress->last_run_time >= progress->interval )
|
||||
{
|
||||
progress->last_run_time = curtime;
|
||||
return progress->callback( dltotal, dlnow, ultotal, ulnow );
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
||||
bool KICAD_CURL_EASY::SetTransferCallback( const TRANSFER_CALLBACK& aCallback, size_t aInterval )
|
||||
{
|
||||
progress = std::make_unique<CURL_PROGRESS>( this, aCallback, (curl_off_t) aInterval );
|
||||
setOption( CURLOPT_XFERINFOFUNCTION, xferinfo );
|
||||
setOption( CURLOPT_XFERINFODATA, progress.get() );
|
||||
setOption( CURLOPT_NOPROGRESS, 0L );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool KICAD_CURL_EASY::SetOutputStream( const std::ostream* aOutput )
|
||||
{
|
||||
curl_easy_setopt( m_CURL, CURLOPT_WRITEFUNCTION, stream_write_callback );
|
||||
curl_easy_setopt( m_CURL, CURLOPT_WRITEDATA, (void*) aOutput );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int KICAD_CURL_EASY::GetTransferTotal( uint64_t& aDownloadedBytes ) const
|
||||
{
|
||||
curl_off_t dl;
|
||||
int result = curl_easy_getinfo( m_CURL, CURLINFO_SIZE_DOWNLOAD_T, &dl );
|
||||
aDownloadedBytes = (uint64_t) dl;
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <project/project_archiver.h>
|
||||
#include <reporter.h>
|
||||
#include <wildcards_and_files_ext.h>
|
||||
#include <wxstream_helper.h>
|
||||
#include <wx/log.h>
|
||||
|
||||
|
||||
|
@ -41,46 +42,6 @@ PROJECT_ARCHIVER::PROJECT_ARCHIVER()
|
|||
|
||||
|
||||
// Unarchive Files code comes from wxWidgets sample/archive/archive.cpp
|
||||
static bool CopyStreamData( wxInputStream& inputStream, wxOutputStream& outputStream,
|
||||
wxFileOffset size )
|
||||
{
|
||||
wxChar buf[128 * 1024];
|
||||
int readSize = 128 * 1024;
|
||||
wxFileOffset copiedData = 0;
|
||||
|
||||
for( ; ; )
|
||||
{
|
||||
if(size != -1 && copiedData + readSize > size )
|
||||
readSize = size - copiedData;
|
||||
|
||||
inputStream.Read( buf, readSize );
|
||||
|
||||
size_t actuallyRead = inputStream.LastRead();
|
||||
outputStream.Write( buf, actuallyRead );
|
||||
|
||||
if( outputStream.LastWrite() != actuallyRead )
|
||||
{
|
||||
wxLogError( _( "Failed to output data." ) );
|
||||
//return false;
|
||||
}
|
||||
|
||||
if( size == -1 )
|
||||
{
|
||||
if( inputStream.Eof() )
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
copiedData += actuallyRead;
|
||||
if( copiedData >= size )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PROJECT_ARCHIVER::Unarchive( const wxString& aSrcFile, const wxString& aDestDir,
|
||||
REPORTER& aReporter )
|
||||
{
|
||||
|
@ -113,30 +74,12 @@ bool PROJECT_ARCHIVER::Unarchive( const wxString& aSrcFile, const wxString& aDes
|
|||
|
||||
wxString fullname = aDestDir + entry->GetName();
|
||||
|
||||
// Ensure the target directory exists and created it if not
|
||||
// Ensure the target directory exists and create it if not
|
||||
wxString t_path = wxPathOnly( fullname );
|
||||
|
||||
if( !wxDirExists( t_path ) )
|
||||
{
|
||||
// To create t_path, we need to create all subdirs from unzipDir
|
||||
// to t_path.
|
||||
wxFileName pathToCreate;
|
||||
pathToCreate.AssignDir( t_path );
|
||||
pathToCreate.MakeRelativeTo( aDestDir );
|
||||
|
||||
// Create the list of subdirs candidates
|
||||
wxArrayString subDirs;
|
||||
subDirs = pathToCreate.GetDirs();
|
||||
pathToCreate.AssignDir( aDestDir );
|
||||
|
||||
for( size_t ii = 0; ii < subDirs.Count(); ii++ )
|
||||
{
|
||||
pathToCreate.AppendDir( subDirs[ii] );
|
||||
wxString currPath = pathToCreate.GetPath();
|
||||
|
||||
if( !wxDirExists( currPath ) )
|
||||
wxMkdir( currPath );
|
||||
}
|
||||
wxFileName::Mkdir( t_path, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
|
||||
}
|
||||
|
||||
// Directory entries need only be created, not extracted (0 size)
|
||||
|
|
|
@ -297,6 +297,7 @@ const std::vector<BITMAP_INFO> g_BitmapInfo = {
|
|||
{ BITMAPS::icon_cvpcb_24, wxT( "icon_cvpcb_24_24.png" ), 24, wxT( "light" ) },
|
||||
{ BITMAPS::icon_footprint_browser, wxT( "icon_footprint_browser_24.png" ), 24, wxT( "light" ) },
|
||||
{ BITMAPS::icon_gerbview_24, wxT( "icon_gerbview_24_24.png" ), 24, wxT( "light" ) },
|
||||
{ BITMAPS::icon_pcm_24, wxT( "icon_pcm_24_24.png" ), 24, wxT( "light" ) },
|
||||
{ BITMAPS::import3d, wxT( "import3d_24.png" ), 24, wxT( "light" ) },
|
||||
{ BITMAPS::image, wxT( "image_24.png" ), 24, wxT( "light" ) },
|
||||
{ BITMAPS::import_brd_file, wxT( "import_brd_file_24.png" ), 24, wxT( "light" ) },
|
||||
|
@ -662,6 +663,7 @@ const std::vector<BITMAP_INFO> g_BitmapInfo = {
|
|||
{ BITMAPS::icon_cvpcb_24, wxT( "icon_cvpcb_24_dark_24.png" ), 24, wxT( "dark" ) },
|
||||
{ BITMAPS::icon_footprint_browser, wxT( "icon_footprint_browser_dark_24.png" ), 24, wxT( "dark" ) },
|
||||
{ BITMAPS::icon_gerbview_24, wxT( "icon_gerbview_24_dark_24.png" ), 24, wxT( "dark" ) },
|
||||
{ BITMAPS::icon_pcm_24, wxT( "icon_pcm_24_dark_24.png" ), 24, wxT( "dark" ) },
|
||||
{ BITMAPS::import3d, wxT( "import3d_dark_24.png" ), 24, wxT( "dark" ) },
|
||||
{ BITMAPS::image, wxT( "image_dark_24.png" ), 24, wxT( "dark" ) },
|
||||
{ BITMAPS::import_brd_file, wxT( "import_brd_file_dark_24.png" ), 24, wxT( "dark" ) },
|
||||
|
@ -956,6 +958,7 @@ const std::vector<BITMAP_INFO> g_BitmapInfo = {
|
|||
{ BITMAPS::icon_bitmap2component, wxT( "icon_bitmap2component_48.png" ), 48, wxT( "light" ) },
|
||||
{ BITMAPS::icon_pagelayout_editor, wxT( "icon_pagelayout_editor_48.png" ), 48, wxT( "light" ) },
|
||||
{ BITMAPS::icon_pcbcalculator, wxT( "icon_pcbcalculator_48.png" ), 48, wxT( "light" ) },
|
||||
{ BITMAPS::icon_pcm, wxT( "icon_pcm_48.png" ), 48, wxT( "light" ) },
|
||||
{ BITMAPS::reannotate_down_left, wxT( "reannotate_down_left_48.png" ), 48, wxT( "light" ) },
|
||||
{ BITMAPS::reannotate_down_right, wxT( "reannotate_down_right_48.png" ), 48, wxT( "light" ) },
|
||||
{ BITMAPS::reannotate_left_down, wxT( "reannotate_left_down_48.png" ), 48, wxT( "light" ) },
|
||||
|
@ -978,6 +981,7 @@ const std::vector<BITMAP_INFO> g_BitmapInfo = {
|
|||
{ BITMAPS::icon_bitmap2component, wxT( "icon_bitmap2component_dark_48.png" ), 48, wxT( "dark" ) },
|
||||
{ BITMAPS::icon_pagelayout_editor, wxT( "icon_pagelayout_editor_dark_48.png" ), 48, wxT( "dark" ) },
|
||||
{ BITMAPS::icon_pcbcalculator, wxT( "icon_pcbcalculator_dark_48.png" ), 48, wxT( "dark" ) },
|
||||
{ BITMAPS::icon_pcm, wxT( "icon_pcm_dark_48.png" ), 48, wxT( "dark" ) },
|
||||
{ BITMAPS::reannotate_down_left, wxT( "reannotate_down_left_dark_48.png" ), 48, wxT( "dark" ) },
|
||||
{ BITMAPS::reannotate_down_right, wxT( "reannotate_down_right_dark_48.png" ), 48, wxT( "dark" ) },
|
||||
{ BITMAPS::reannotate_left_down, wxT( "reannotate_left_down_dark_48.png" ), 48, wxT( "dark" ) },
|
||||
|
|
|
@ -266,6 +266,8 @@ enum class BITMAPS : unsigned int
|
|||
icon_pcbnew_16,
|
||||
icon_pcbnew_24,
|
||||
icon_pcbnew_32,
|
||||
icon_pcm,
|
||||
icon_pcm_24,
|
||||
image,
|
||||
import,
|
||||
import3d,
|
||||
|
|
|
@ -32,6 +32,10 @@
|
|||
* so including kicad_curl.h could be needed in a few sources
|
||||
*/
|
||||
|
||||
#include <functional>
|
||||
#include <kicad_curl/kicad_curl.h>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
typedef void CURL;
|
||||
|
@ -56,6 +60,10 @@ struct curl_slist;
|
|||
*/
|
||||
|
||||
|
||||
typedef std::function<int( size_t, size_t, size_t, size_t )> TRANSFER_CALLBACK;
|
||||
struct CURL_PROGRESS;
|
||||
|
||||
|
||||
class KICAD_CURL_EASY
|
||||
{
|
||||
public:
|
||||
|
@ -66,10 +74,8 @@ public:
|
|||
* Function perform
|
||||
* equivalent to curl_easy_perform. Executes the request
|
||||
* that was previously setup.
|
||||
*
|
||||
* @throw IO_ERROR, if there is a CURL request error
|
||||
*/
|
||||
void Perform();
|
||||
int Perform();
|
||||
|
||||
/**
|
||||
* Function SetHeader
|
||||
|
@ -117,18 +123,21 @@ public:
|
|||
*/
|
||||
const std::string GetErrorText( int aCode );
|
||||
|
||||
int GetTransferTotal( uint64_t& aDownloadedBytes ) const;
|
||||
|
||||
/**
|
||||
* Function GetBuffer
|
||||
* returns a const reference to the received data buffer
|
||||
*/
|
||||
const std::string& GetBuffer()
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
const std::string& GetBuffer() { return m_buffer; }
|
||||
|
||||
/// Escapes a string for use as a URL
|
||||
std::string Escape( const std::string& aUrl );
|
||||
|
||||
bool SetTransferCallback( const TRANSFER_CALLBACK& aCallback, size_t aInterval );
|
||||
|
||||
bool SetOutputStream( const std::ostream* aOutput );
|
||||
|
||||
private:
|
||||
/**
|
||||
* Function setOption
|
||||
|
@ -138,12 +147,16 @@ private:
|
|||
* @param aArg is the argument being passed to CURL, ensure it is the right type per manual
|
||||
* @return int - a CURL error code, will return CURLE_OK unless a problem was encountered
|
||||
*/
|
||||
template <typename T> int setOption( int aOption, T aArg );
|
||||
template <typename T>
|
||||
int setOption( int aOption, T aArg );
|
||||
|
||||
static int xferinfo( void*, curl_off_t, curl_off_t, curl_off_t, curl_off_t );
|
||||
|
||||
CURL* m_CURL;
|
||||
curl_slist* m_headers;
|
||||
std::string m_buffer;
|
||||
std::unique_ptr<CURL_PROGRESS> progress;
|
||||
};
|
||||
|
||||
|
||||
#endif // KICAD_CURL_EASY_H_
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2020 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 WXSTREAM_HELPER_H
|
||||
#define WXSTREAM_HELPER_H
|
||||
|
||||
#include <wx/log.h>
|
||||
#include <wx/wfstream.h>
|
||||
|
||||
|
||||
static bool CopyStreamData( wxInputStream& inputStream, wxOutputStream& outputStream,
|
||||
wxFileOffset size )
|
||||
{
|
||||
wxChar buf[128 * 1024];
|
||||
int readSize = 128 * 1024;
|
||||
wxFileOffset copiedData = 0;
|
||||
|
||||
for( ; ; )
|
||||
{
|
||||
if(size != -1 && copiedData + readSize > size )
|
||||
readSize = size - copiedData;
|
||||
|
||||
inputStream.Read( buf, readSize );
|
||||
|
||||
size_t actuallyRead = inputStream.LastRead();
|
||||
outputStream.Write( buf, actuallyRead );
|
||||
|
||||
if( outputStream.LastWrite() != actuallyRead )
|
||||
{
|
||||
wxLogError( _("Failed to output data") );
|
||||
//return false;
|
||||
}
|
||||
|
||||
if( size == -1 )
|
||||
{
|
||||
if( inputStream.Eof() )
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
copiedData += actuallyRead;
|
||||
if( copiedData >= size )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#endif // WXSTREAM_HELPER_H
|
|
@ -13,6 +13,11 @@ include_directories(
|
|||
${INC_AFTER}
|
||||
)
|
||||
|
||||
if ( KICAD_PCM )
|
||||
add_definitions( -DPCM )
|
||||
add_subdirectory( pcm )
|
||||
include_directories( ./pcm )
|
||||
endif ( KICAD_PCM )
|
||||
|
||||
set( KICAD_SRCS
|
||||
dialogs/dialog_template_selector_base.cpp
|
||||
|
@ -91,6 +96,10 @@ else()
|
|||
)
|
||||
endif()
|
||||
|
||||
if( KICAD_PCM )
|
||||
target_link_libraries( kicad pcm )
|
||||
endif()
|
||||
|
||||
install( TARGETS kicad
|
||||
DESTINATION ${KICAD_BIN}
|
||||
COMPONENT binary
|
||||
|
|
|
@ -136,5 +136,11 @@ void PANEL_KICAD_LAUNCHER::CreateLaunchers()
|
|||
_( "Edit drawing sheet borders and title blocks for use in schematics and PCB "
|
||||
"designs" ) );
|
||||
|
||||
#ifdef PCM
|
||||
addLauncher( KICAD_MANAGER_ACTIONS::showPluginManager,
|
||||
KiBitmap( BITMAPS::icon_pcm, 48 ),
|
||||
_( "Manage downloadable packages from KiCad and 3rd party repositories" ) );
|
||||
#endif
|
||||
|
||||
Layout();
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
*/
|
||||
|
||||
#include "kicad_settings.h"
|
||||
#include "nlohmann/json.hpp"
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <settings/parameters.h>
|
||||
|
||||
|
||||
|
@ -46,6 +46,7 @@ KICAD_SETTINGS::KICAD_SETTINGS() :
|
|||
{
|
||||
js.push_back( nlohmann::json( { { "name", pair.first.ToUTF8() },
|
||||
{ "url", pair.second.ToUTF8() } } ) );
|
||||
}
|
||||
|
||||
return js;
|
||||
},
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
class KICAD_SETTINGS : public APP_SETTINGS_BASE
|
||||
{
|
||||
public:
|
||||
|
||||
KICAD_SETTINGS();
|
||||
|
||||
virtual ~KICAD_SETTINGS() {}
|
||||
|
@ -44,7 +43,6 @@ public:
|
|||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
virtual std::string getLegacyFrameName() const override { return "KicadFrame"; }
|
||||
};
|
||||
|
||||
|
|
|
@ -157,6 +157,9 @@ void KICAD_MANAGER_FRAME::ReCreateMenuBar()
|
|||
toolsMenu->Add( KICAD_MANAGER_ACTIONS::convertImage );
|
||||
toolsMenu->Add( KICAD_MANAGER_ACTIONS::showCalculator );
|
||||
toolsMenu->Add( KICAD_MANAGER_ACTIONS::editDrawingSheet );
|
||||
#ifdef PCM
|
||||
toolsMenu->Add( KICAD_MANAGER_ACTIONS::showPluginManager );
|
||||
#endif
|
||||
|
||||
toolsMenu->AppendSeparator();
|
||||
toolsMenu->Add( _( "Edit Local File..." ),
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
# Add all the warnings to the files
|
||||
if( COMPILER_SUPPORTS_WARNINGS )
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARN_FLAGS_CXX}")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARN_FLAGS_C}")
|
||||
endif()
|
||||
|
||||
include_directories( BEFORE ${INC_BEFORE} )
|
||||
|
||||
add_definitions( -DPCM )
|
||||
|
||||
include_directories(
|
||||
${CMAKE_SOURCE_DIR}/common
|
||||
${CMAKE_SOURCE_DIR}/kicad
|
||||
)
|
||||
|
||||
set ( PCM_DLG_SRCS
|
||||
dialogs/dialog_manage_repositories_base.cpp
|
||||
dialogs/dialog_manage_repositories.cpp
|
||||
dialogs/dialog_pcm_base.cpp
|
||||
dialogs/dialog_pcm.cpp
|
||||
dialogs/dialog_pcm_progress_base.cpp
|
||||
dialogs/dialog_pcm_progress.cpp
|
||||
dialogs/panel_package_base.cpp
|
||||
dialogs/panel_package.cpp
|
||||
dialogs/panel_packages_view_base.cpp
|
||||
dialogs/panel_packages_view.cpp
|
||||
)
|
||||
|
||||
set( PCM_SRCS
|
||||
${PCM_DLG_SRCS}
|
||||
pcm.cpp
|
||||
pcm_data.cpp
|
||||
pcm_task_manager.cpp
|
||||
)
|
||||
|
||||
add_library( pcm STATIC
|
||||
${PCM_SRCS}
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
pcm PUBLIC dialogs
|
||||
)
|
||||
|
||||
target_link_libraries( pcm
|
||||
${wxWidgets_LIBRARIES}
|
||||
common
|
||||
picosha2
|
||||
nlohmann_json_schema_validator
|
||||
)
|
||||
|
||||
INSTALL( DIRECTORY
|
||||
schemas
|
||||
DESTINATION ${KICAD_DATA}
|
||||
COMPONENT Runtime
|
||||
)
|
|
@ -0,0 +1,253 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 Andrew Lutsenko, anlutsenko at gmail dot com
|
||||
* Copyright (C) 1992-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 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dialog_manage_repositories.h"
|
||||
#include "bitmaps/bitmap_types.h"
|
||||
#include "bitmaps/bitmaps_list.h"
|
||||
#include "grid_tricks.h"
|
||||
#include "widgets/wx_grid.h"
|
||||
|
||||
|
||||
#define GRID_CELL_MARGIN 4
|
||||
|
||||
|
||||
DIALOG_MANAGE_REPOSITORIES::DIALOG_MANAGE_REPOSITORIES(
|
||||
wxWindow* parent, std::shared_ptr<PLUGIN_CONTENT_MANAGER> pcm ) :
|
||||
DIALOG_MANAGE_REPOSITORIES_BASE( parent ),
|
||||
m_pcm( pcm )
|
||||
{
|
||||
m_buttonAdd->SetBitmap( KiBitmap( BITMAPS::small_plus ) );
|
||||
m_buttonRemove->SetBitmap( KiBitmap( BITMAPS::small_trash ) );
|
||||
m_buttonMoveUp->SetBitmap( KiBitmap( BITMAPS::small_up ) );
|
||||
m_buttonMoveDown->SetBitmap( KiBitmap( BITMAPS::small_down ) );
|
||||
|
||||
m_grid->PushEventHandler( new GRID_TRICKS( m_grid ) );
|
||||
|
||||
for( int col = 0; col < m_grid->GetNumberCols(); col++ )
|
||||
{
|
||||
const wxString& heading = m_grid->GetColLabelValue( col );
|
||||
int headingWidth = GetTextExtent( heading ).x + 2 * GRID_CELL_MARGIN;
|
||||
|
||||
// Set the minimal width to the column label size.
|
||||
m_grid->SetColMinimalWidth( col, headingWidth );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_MANAGE_REPOSITORIES::setColumnWidths()
|
||||
{
|
||||
for( int col = 0; col < m_grid->GetNumberCols(); col++ )
|
||||
{
|
||||
// Set the width to see the full contents
|
||||
m_grid->SetColSize( col, m_grid->GetVisibleWidth( col, true, true, false ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_MANAGE_REPOSITORIES::OnAddButtonClicked( wxCommandEvent& event )
|
||||
{
|
||||
wxTextEntryDialog* entry_dialog = new wxTextEntryDialog(
|
||||
this, _( "Please enter fully qualified repository url" ), _( "Add repository" ) );
|
||||
|
||||
if( entry_dialog->ShowModal() == wxID_OK )
|
||||
{
|
||||
PCM_REPOSITORY repository;
|
||||
wxString url = entry_dialog->GetValue();
|
||||
|
||||
const auto find_row = [&]( const int col, const wxString& val )
|
||||
{
|
||||
for( int row = 0; row < m_grid->GetNumberRows(); row++ )
|
||||
{
|
||||
if( m_grid->GetCellValue( row, col ) == val )
|
||||
return row;
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
|
||||
int matching_row;
|
||||
|
||||
if( ( matching_row = find_row( 1, url ) ) >= 0 )
|
||||
{
|
||||
selectRow( matching_row );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( m_pcm->FetchRepository( url, repository ) )
|
||||
{
|
||||
wxString name = repository.name;
|
||||
int increment = 1;
|
||||
|
||||
while( find_row( 0, name ) >= 0 )
|
||||
name = wxString::Format( "%s (%d)", repository.name, increment++ );
|
||||
|
||||
m_grid->Freeze();
|
||||
|
||||
m_grid->AppendRows();
|
||||
int row = m_grid->GetNumberRows() - 1;
|
||||
|
||||
m_grid->SetCellValue( row, 0, name );
|
||||
m_grid->SetCellValue( row, 1, url );
|
||||
|
||||
setColumnWidths();
|
||||
m_grid->Thaw();
|
||||
|
||||
selectRow( row );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
entry_dialog->Destroy();
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_MANAGE_REPOSITORIES::OnRemoveButtonClicked( wxCommandEvent& event )
|
||||
{
|
||||
auto selectedRows = m_grid->GetSelectedRows();
|
||||
|
||||
// If nothing is selected or multiple rows are selected don't do anything.
|
||||
if( selectedRows.size() != 1 )
|
||||
{
|
||||
wxBell();
|
||||
return;
|
||||
}
|
||||
|
||||
int selectedRow = selectedRows[0];
|
||||
m_grid->DeleteRows( selectedRow );
|
||||
setColumnWidths();
|
||||
|
||||
if( m_grid->GetNumberRows() > 0 )
|
||||
m_grid->SelectRow( selectedRow == m_grid->GetNumberRows() ? selectedRow - 1 : selectedRow );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_MANAGE_REPOSITORIES::OnMoveUpButtonClicked( wxCommandEvent& event )
|
||||
{
|
||||
auto selectedRows = m_grid->GetSelectedRows();
|
||||
|
||||
// If nothing is selected or multiple rows are selected don't do anything.
|
||||
if( selectedRows.size() != 1 )
|
||||
return;
|
||||
|
||||
int selectedRow = selectedRows[0];
|
||||
|
||||
// If first row is selected, then it can't go any further up.
|
||||
if( selectedRow == 0 )
|
||||
{
|
||||
wxBell();
|
||||
return;
|
||||
}
|
||||
|
||||
swapRows( selectedRow, selectedRow - 1 );
|
||||
|
||||
selectRow( selectedRow - 1 );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_MANAGE_REPOSITORIES::OnMoveDownButtonClicked( wxCommandEvent& event )
|
||||
{
|
||||
auto selectedRows = m_grid->GetSelectedRows();
|
||||
|
||||
// If nothing is selected or multiple rows are selected don't do anything.
|
||||
if( selectedRows.size() != 1 )
|
||||
return;
|
||||
|
||||
int selectedRow = selectedRows[0];
|
||||
|
||||
// If last row is selected, then it can't go any further down.
|
||||
if( selectedRow + 1 == m_grid->GetNumberRows() )
|
||||
{
|
||||
wxBell();
|
||||
return;
|
||||
}
|
||||
|
||||
swapRows( selectedRow, selectedRow + 1 );
|
||||
|
||||
selectRow( selectedRow + 1 );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_MANAGE_REPOSITORIES::swapRows( int aRowA, int aRowB )
|
||||
{
|
||||
m_grid->Freeze();
|
||||
|
||||
wxString tempStr;
|
||||
|
||||
for( int column = 0; column < m_grid->GetNumberCols(); column++ )
|
||||
{
|
||||
tempStr = m_grid->GetCellValue( aRowA, column );
|
||||
m_grid->SetCellValue( aRowA, column, m_grid->GetCellValue( aRowB, column ) );
|
||||
m_grid->SetCellValue( aRowB, column, tempStr );
|
||||
}
|
||||
|
||||
m_grid->Thaw();
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_MANAGE_REPOSITORIES::OnGridCellClicked( wxGridEvent& event )
|
||||
{
|
||||
selectRow( event.GetRow() );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_MANAGE_REPOSITORIES::selectRow( int aRow )
|
||||
{
|
||||
m_grid->ClearSelection();
|
||||
m_grid->SelectRow( aRow );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_MANAGE_REPOSITORIES::SetData( const STRING_PAIR_LIST& aData )
|
||||
{
|
||||
m_grid->Freeze();
|
||||
|
||||
m_grid->DeleteRows( 0, m_grid->GetNumberRows() );
|
||||
m_grid->AppendRows( aData.size() );
|
||||
|
||||
for( size_t i = 0; i < aData.size(); i++ )
|
||||
{
|
||||
m_grid->SetCellValue( i, 0, aData[i].first );
|
||||
m_grid->SetCellValue( i, 1, aData[i].second );
|
||||
}
|
||||
|
||||
setColumnWidths();
|
||||
|
||||
m_grid->Thaw();
|
||||
}
|
||||
|
||||
|
||||
STRING_PAIR_LIST DIALOG_MANAGE_REPOSITORIES::GetData()
|
||||
{
|
||||
STRING_PAIR_LIST result;
|
||||
|
||||
for( int i = 0; i < m_grid->GetNumberRows(); i++ )
|
||||
{
|
||||
result.push_back(
|
||||
std::make_pair( m_grid->GetCellValue( i, 0 ), m_grid->GetCellValue( i, 1 ) ) );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_MANAGE_REPOSITORIES::OnSaveClicked( wxCommandEvent& event )
|
||||
{
|
||||
EndModal( wxID_SAVE );
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 Andrew Lutsenko, anlutsenko at gmail dot com
|
||||
* Copyright (C) 1992-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 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_MANAGE_REPOSITORIES_H_
|
||||
#define DIALOG_MANAGE_REPOSITORIES_H_
|
||||
|
||||
#include "dialog_manage_repositories_base.h"
|
||||
#include "pcm.h"
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
|
||||
/** Implementing DIALOG_MANAGE_REPOSITORIES_BASE */
|
||||
class DIALOG_MANAGE_REPOSITORIES : public DIALOG_MANAGE_REPOSITORIES_BASE
|
||||
{
|
||||
protected:
|
||||
// Handlers for DIALOG_MANAGE_REPOSITORIES_BASE events.
|
||||
void OnAddButtonClicked( wxCommandEvent& event ) override;
|
||||
void OnRemoveButtonClicked( wxCommandEvent& event ) override;
|
||||
void OnMoveUpButtonClicked( wxCommandEvent& event ) override;
|
||||
void OnMoveDownButtonClicked( wxCommandEvent& event ) override;
|
||||
void OnGridCellClicked( wxGridEvent& event ) override;
|
||||
void OnSaveClicked( wxCommandEvent& event ) override;
|
||||
|
||||
public:
|
||||
/** Constructor */
|
||||
DIALOG_MANAGE_REPOSITORIES( wxWindow* parent, std::shared_ptr<PLUGIN_CONTENT_MANAGER> aPcm );
|
||||
void SetData( const STRING_PAIR_LIST& aData );
|
||||
STRING_PAIR_LIST GetData();
|
||||
|
||||
private:
|
||||
void swapRows( int aRowA, int aRowB );
|
||||
void selectRow( int aRow );
|
||||
void setColumnWidths();
|
||||
|
||||
std::shared_ptr<PLUGIN_CONTENT_MANAGER> m_pcm;
|
||||
};
|
||||
|
||||
#endif // DIALOG_MANAGE_REPOSITORIES_H_
|
|
@ -0,0 +1,110 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Oct 26 2018)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "widgets/wx_grid.h"
|
||||
|
||||
#include "dialog_manage_repositories_base.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DIALOG_MANAGE_REPOSITORIES_BASE::DIALOG_MANAGE_REPOSITORIES_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
|
||||
{
|
||||
this->SetSizeHints( wxSize( 500,300 ), wxDefaultSize );
|
||||
|
||||
wxBoxSizer* m_MainSizer;
|
||||
m_MainSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxBoxSizer* m_TopSizer;
|
||||
m_TopSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_grid = new WX_GRID( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
|
||||
// Grid
|
||||
m_grid->CreateGrid( 5, 2 );
|
||||
m_grid->EnableEditing( false );
|
||||
m_grid->EnableGridLines( true );
|
||||
m_grid->EnableDragGridSize( false );
|
||||
m_grid->SetMargins( 0, 0 );
|
||||
|
||||
// Columns
|
||||
m_grid->EnableDragColMove( false );
|
||||
m_grid->EnableDragColSize( true );
|
||||
m_grid->SetColLabelSize( 30 );
|
||||
m_grid->SetColLabelValue( 0, _("Name") );
|
||||
m_grid->SetColLabelValue( 1, _("URL") );
|
||||
m_grid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
|
||||
|
||||
// Rows
|
||||
m_grid->EnableDragRowSize( true );
|
||||
m_grid->SetRowLabelSize( 0 );
|
||||
m_grid->SetRowLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
|
||||
|
||||
// Label Appearance
|
||||
|
||||
// Cell Defaults
|
||||
m_grid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
|
||||
m_TopSizer->Add( m_grid, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_MainSizer->Add( m_TopSizer, 1, wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* m_BottomSizer;
|
||||
m_BottomSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_buttonAdd = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_BottomSizer->Add( m_buttonAdd, 0, wxALL, 5 );
|
||||
|
||||
m_buttonRemove = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_BottomSizer->Add( m_buttonRemove, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_BottomSizer->Add( 20, 0, 0, wxEXPAND, 5 );
|
||||
|
||||
m_buttonMoveUp = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_BottomSizer->Add( m_buttonMoveUp, 0, wxALL, 5 );
|
||||
|
||||
m_buttonMoveDown = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_BottomSizer->Add( m_buttonMoveDown, 0, wxALL, 5 );
|
||||
|
||||
m_sdbSizer1 = new wxStdDialogButtonSizer();
|
||||
m_sdbSizer1Save = new wxButton( this, wxID_SAVE );
|
||||
m_sdbSizer1->AddButton( m_sdbSizer1Save );
|
||||
m_sdbSizer1Cancel = new wxButton( this, wxID_CANCEL );
|
||||
m_sdbSizer1->AddButton( m_sdbSizer1Cancel );
|
||||
m_sdbSizer1->Realize();
|
||||
|
||||
m_BottomSizer->Add( m_sdbSizer1, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_MainSizer->Add( m_BottomSizer, 0, wxEXPAND, 5 );
|
||||
|
||||
|
||||
this->SetSizer( m_MainSizer );
|
||||
this->Layout();
|
||||
|
||||
this->Centre( wxBOTH );
|
||||
|
||||
// Connect Events
|
||||
m_grid->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_MANAGE_REPOSITORIES_BASE::OnGridCellClicked ), NULL, this );
|
||||
m_buttonAdd->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MANAGE_REPOSITORIES_BASE::OnAddButtonClicked ), NULL, this );
|
||||
m_buttonRemove->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MANAGE_REPOSITORIES_BASE::OnRemoveButtonClicked ), NULL, this );
|
||||
m_buttonMoveUp->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MANAGE_REPOSITORIES_BASE::OnMoveUpButtonClicked ), NULL, this );
|
||||
m_buttonMoveDown->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MANAGE_REPOSITORIES_BASE::OnMoveDownButtonClicked ), NULL, this );
|
||||
m_sdbSizer1Save->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MANAGE_REPOSITORIES_BASE::OnSaveClicked ), NULL, this );
|
||||
}
|
||||
|
||||
DIALOG_MANAGE_REPOSITORIES_BASE::~DIALOG_MANAGE_REPOSITORIES_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
m_grid->Disconnect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_MANAGE_REPOSITORIES_BASE::OnGridCellClicked ), NULL, this );
|
||||
m_buttonAdd->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MANAGE_REPOSITORIES_BASE::OnAddButtonClicked ), NULL, this );
|
||||
m_buttonRemove->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MANAGE_REPOSITORIES_BASE::OnRemoveButtonClicked ), NULL, this );
|
||||
m_buttonMoveUp->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MANAGE_REPOSITORIES_BASE::OnMoveUpButtonClicked ), NULL, this );
|
||||
m_buttonMoveDown->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MANAGE_REPOSITORIES_BASE::OnMoveDownButtonClicked ), NULL, this );
|
||||
m_sdbSizer1Save->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MANAGE_REPOSITORIES_BASE::OnSaveClicked ), NULL, this );
|
||||
|
||||
}
|
|
@ -0,0 +1,496 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
<wxFormBuilder_Project>
|
||||
<FileVersion major="1" minor="15" />
|
||||
<object class="Project" expanded="1">
|
||||
<property name="class_decoration">; </property>
|
||||
<property name="code_generation">C++</property>
|
||||
<property name="disconnect_events">1</property>
|
||||
<property name="disconnect_mode">source_name</property>
|
||||
<property name="disconnect_php_events">0</property>
|
||||
<property name="disconnect_python_events">0</property>
|
||||
<property name="embedded_files_path"></property>
|
||||
<property name="encoding">UTF-8</property>
|
||||
<property name="event_generation">connect</property>
|
||||
<property name="file">dialog_manage_repositories_base</property>
|
||||
<property name="first_id">1000</property>
|
||||
<property name="help_provider">none</property>
|
||||
<property name="indent_with_spaces"></property>
|
||||
<property name="internationalize">1</property>
|
||||
<property name="name">dialog_manage_repositories_base</property>
|
||||
<property name="namespace"></property>
|
||||
<property name="path">./</property>
|
||||
<property name="precompiled_header"></property>
|
||||
<property name="relative_path">1</property>
|
||||
<property name="skip_lua_events">1</property>
|
||||
<property name="skip_php_events">1</property>
|
||||
<property name="skip_python_events">1</property>
|
||||
<property name="ui_table">UI</property>
|
||||
<property name="use_enum">0</property>
|
||||
<property name="use_microsoft_bom">0</property>
|
||||
<object class="Dialog" expanded="1">
|
||||
<property name="aui_managed">0</property>
|
||||
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
|
||||
<property name="bg"></property>
|
||||
<property name="center">wxBOTH</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="event_handler">impl_virtual</property>
|
||||
<property name="extra_style"></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">500,300</property>
|
||||
<property name="name">DIALOG_MANAGE_REPOSITORIES_BASE</property>
|
||||
<property name="pos"></property>
|
||||
<property name="size">500,300</property>
|
||||
<property name="style">wxDEFAULT_DIALOG_STYLE</property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="title">Manage Repositores</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">m_MainSizer</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">m_TopSizer</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL|wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxGrid" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="autosize_cols">0</property>
|
||||
<property name="autosize_rows">0</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_TOP</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">30</property>
|
||||
<property name="col_label_values">"Name" "URL"</property>
|
||||
<property name="col_label_vert_alignment">wxALIGN_CENTER</property>
|
||||
<property name="cols">2</property>
|
||||
<property name="column_sizes"></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_col_move">0</property>
|
||||
<property name="drag_col_size">1</property>
|
||||
<property name="drag_grid_size">0</property>
|
||||
<property name="drag_row_size">1</property>
|
||||
<property name="editing">0</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</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"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_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">Resizable</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">5</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="OnGridCellLeftClick">OnGridCellClicked</event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">m_BottomSizer</property>
|
||||
<property name="orient">wxHORIZONTAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBitmapButton" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="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 repository</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_buttonAdd</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">OnAddButtonClicked</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBitmapButton" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="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">Remove repository</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_buttonRemove</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">OnRemoveButtonClicked</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="spacer" expanded="1">
|
||||
<property name="height">0</property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="width">20</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBitmapButton" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="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">Move Up</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_buttonMoveUp</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">OnMoveUpButtonClicked</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBitmapButton" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="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">Move Down</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_buttonMoveDown</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">OnMoveDownButtonClicked</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxStdDialogButtonSizer" expanded="1">
|
||||
<property name="Apply">0</property>
|
||||
<property name="Cancel">1</property>
|
||||
<property name="ContextHelp">0</property>
|
||||
<property name="Help">0</property>
|
||||
<property name="No">0</property>
|
||||
<property name="OK">0</property>
|
||||
<property name="Save">1</property>
|
||||
<property name="Yes">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">m_sdbSizer1</property>
|
||||
<property name="permission">protected</property>
|
||||
<event name="OnSaveButtonClick">OnSaveClicked</event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</wxFormBuilder_Project>
|
|
@ -0,0 +1,64 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Oct 26 2018)
|
||||
// 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 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/dialog.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class DIALOG_MANAGE_REPOSITORIES_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class DIALOG_MANAGE_REPOSITORIES_BASE : public wxDialog
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
WX_GRID* m_grid;
|
||||
wxBitmapButton* m_buttonAdd;
|
||||
wxBitmapButton* m_buttonRemove;
|
||||
wxBitmapButton* m_buttonMoveUp;
|
||||
wxBitmapButton* m_buttonMoveDown;
|
||||
wxStdDialogButtonSizer* m_sdbSizer1;
|
||||
wxButton* m_sdbSizer1Save;
|
||||
wxButton* m_sdbSizer1Cancel;
|
||||
|
||||
// Virtual event handlers, overide them in your derived class
|
||||
virtual void OnGridCellClicked( wxGridEvent& event ) { event.Skip(); }
|
||||
virtual void OnAddButtonClicked( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnRemoveButtonClicked( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnMoveUpButtonClicked( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnMoveDownButtonClicked( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnSaveClicked( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
DIALOG_MANAGE_REPOSITORIES_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Manage Repositores"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 500,300 ), long style = wxDEFAULT_DIALOG_STYLE );
|
||||
~DIALOG_MANAGE_REPOSITORIES_BASE();
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,435 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 Andrew Lutsenko, anlutsenko at gmail dot com
|
||||
* Copyright (C) 1992-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 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dialog_pcm.h"
|
||||
#include "bitmaps.h"
|
||||
#include "dialog_manage_repositories.h"
|
||||
#include "grid_tricks.h"
|
||||
#include "ki_exception.h"
|
||||
#include "kicad_curl/kicad_curl_easy.h"
|
||||
#include "kicad_settings.h"
|
||||
#include "pcm_task_manager.h"
|
||||
#include "pgm_base.h"
|
||||
#include "settings/settings_manager.h"
|
||||
#include "thread"
|
||||
#include "widgets/wx_progress_reporters.h"
|
||||
#include "widgets/wx_grid.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <wx/filedlg.h>
|
||||
#include <wx/msgdlg.h>
|
||||
|
||||
|
||||
#define GRID_CELL_MARGIN 4
|
||||
|
||||
|
||||
static std::vector<std::pair<PCM_PACKAGE_TYPE, wxString>> PACKAGE_TYPE_LIST = {
|
||||
{ PT_PLUGIN, _( "Plugins (%d)" ) },
|
||||
{ PT_LIBRARY, _( "Libraries (%d)" ) }
|
||||
};
|
||||
|
||||
|
||||
DIALOG_PCM::DIALOG_PCM( wxWindow* parent ) : DIALOG_PCM_BASE( parent )
|
||||
{
|
||||
m_defaultBitmap = KiBitmap( BITMAPS::icon_pcm );
|
||||
|
||||
m_pcm = std::make_shared<PLUGIN_CONTENT_MANAGER>( this );
|
||||
|
||||
m_gridPendingActions->PushEventHandler( new GRID_TRICKS( m_gridPendingActions ) );
|
||||
|
||||
m_discardActionButton->SetBitmap( KiBitmap( BITMAPS::small_trash ) );
|
||||
m_panelPending->Layout();
|
||||
|
||||
m_installedPanel = new PANEL_PACKAGES_VIEW( m_panelInstalledHolder, m_pcm );
|
||||
m_panelInstalledHolder->GetSizer()->Add( m_installedPanel, 1, wxEXPAND );
|
||||
m_panelInstalledHolder->Layout();
|
||||
|
||||
for( const auto& entry : PACKAGE_TYPE_LIST )
|
||||
{
|
||||
PANEL_PACKAGES_VIEW* panel = new PANEL_PACKAGES_VIEW( m_contentNotebook, m_pcm );
|
||||
m_contentNotebook->AddPage( panel, wxString::Format( std::get<1>( entry ), 0 ) );
|
||||
m_repositoryContentPanels.insert( { std::get<0>( entry ), panel } );
|
||||
}
|
||||
|
||||
m_dialogNotebook->SetPageText( 0, wxString::Format( _( "Repository (%d)" ), 0 ) );
|
||||
|
||||
m_callback = [this]( const PACKAGE_VIEW_DATA& aData, PCM_PACKAGE_ACTION aAction,
|
||||
const wxString& aVersion )
|
||||
{
|
||||
m_gridPendingActions->Freeze();
|
||||
|
||||
PCM_PACKAGE_STATE new_state;
|
||||
|
||||
m_gridPendingActions->AppendRows();
|
||||
int row = m_gridPendingActions->GetNumberRows() - 1;
|
||||
|
||||
m_gridPendingActions->SetCellValue( row, PENDING_COL_NAME, aData.package.name );
|
||||
m_gridPendingActions->SetCellValue( row, PENDING_COL_REPOSITORY, aData.repository_name );
|
||||
|
||||
if( aAction == PPA_INSTALL )
|
||||
{
|
||||
m_gridPendingActions->SetCellValue( row, PENDING_COL_ACTION, _( "Install" ) );
|
||||
m_gridPendingActions->SetCellValue( row, PENDING_COL_VERSION, aVersion );
|
||||
|
||||
m_pendingActions.emplace_back( aAction, aData.repository_id, aData.package, aVersion );
|
||||
|
||||
new_state = PPS_PENDING_INSTALL;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_gridPendingActions->SetCellValue( row, PENDING_COL_ACTION, _( "Uninstall" ) );
|
||||
m_gridPendingActions->SetCellValue(
|
||||
row, PENDING_COL_VERSION,
|
||||
m_pcm->GetInstalledPackageVersion( aData.package.identifier ) );
|
||||
|
||||
m_pendingActions.emplace_back( aAction, aData.repository_id, aData.package, aVersion );
|
||||
|
||||
new_state = PPS_PENDING_UNINSTALL;
|
||||
}
|
||||
|
||||
m_gridPendingActions->Thaw();
|
||||
|
||||
updatePendingActionsTab();
|
||||
|
||||
m_installedPanel->SetPackageState( aData.package.identifier, new_state );
|
||||
|
||||
for( const auto& entry : m_repositoryContentPanels )
|
||||
entry.second->SetPackageState( aData.package.identifier, new_state );
|
||||
};
|
||||
|
||||
setInstalledPackages();
|
||||
updatePendingActionsTab();
|
||||
|
||||
m_dialogNotebook->SetSelection( 0 );
|
||||
|
||||
|
||||
SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
|
||||
KICAD_SETTINGS* app_settings = mgr.GetAppSettings<KICAD_SETTINGS>();
|
||||
|
||||
m_pcm->SetRepositoryList( app_settings->m_PcmRepositories );
|
||||
|
||||
setRepositoryListFromPcm();
|
||||
|
||||
SetDefaultItem( m_closeButton );
|
||||
|
||||
for( int col = 0; col < m_gridPendingActions->GetNumberCols(); col++ )
|
||||
{
|
||||
const wxString& heading = m_gridPendingActions->GetColLabelValue( col );
|
||||
int headingWidth = GetTextExtent( heading ).x + 2 * GRID_CELL_MARGIN;
|
||||
|
||||
// Set the minimal width to the column label size.
|
||||
m_gridPendingActions->SetColMinimalWidth( col, headingWidth );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DIALOG_PCM::~DIALOG_PCM()
|
||||
{
|
||||
m_gridPendingActions->PopEventHandler( true );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PCM::OnCloseClicked( wxCommandEvent& event )
|
||||
{
|
||||
if( m_pendingActions.size() == 0
|
||||
|| wxMessageBox( _( "Are you sure you want to close the package manager "
|
||||
"and discard pending changes?" ),
|
||||
_( "Plugin and Content Manager" ), wxICON_QUESTION | wxYES_NO, this )
|
||||
== wxYES )
|
||||
{
|
||||
EndModal( wxID_OK );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PCM::OnManageRepositoriesClicked( wxCommandEvent& event )
|
||||
{
|
||||
DIALOG_MANAGE_REPOSITORIES* dialog = new DIALOG_MANAGE_REPOSITORIES( this, m_pcm );
|
||||
|
||||
STRING_PAIR_LIST dialog_data;
|
||||
STRING_TUPLE_LIST repo_list = m_pcm->GetRepositoryList();
|
||||
|
||||
for( const auto& repo : repo_list )
|
||||
{
|
||||
dialog_data.push_back( std::make_pair( std::get<1>( repo ), std::get<2>( repo ) ) );
|
||||
}
|
||||
|
||||
dialog->SetData( dialog_data );
|
||||
|
||||
if( dialog->ShowModal() == wxID_SAVE )
|
||||
{
|
||||
dialog_data = dialog->GetData();
|
||||
m_pcm->SetRepositoryList( dialog_data );
|
||||
|
||||
SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
|
||||
KICAD_SETTINGS* app_settings = mgr.GetAppSettings<KICAD_SETTINGS>();
|
||||
|
||||
app_settings->m_PcmRepositories = std::move( dialog_data );
|
||||
|
||||
setRepositoryListFromPcm();
|
||||
}
|
||||
|
||||
dialog->Destroy();
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PCM::setRepositoryListFromPcm()
|
||||
{
|
||||
STRING_TUPLE_LIST repositories = m_pcm->GetRepositoryList();
|
||||
|
||||
m_choiceRepository->Clear();
|
||||
|
||||
for( const auto& entry : repositories )
|
||||
{
|
||||
m_choiceRepository->Append( std::get<1>( entry ),
|
||||
new wxStringClientData( std::get<0>( entry ) ) );
|
||||
}
|
||||
|
||||
if( repositories.size() > 0 )
|
||||
{
|
||||
m_choiceRepository->SetSelection( 0 );
|
||||
m_selectedRepositoryId = std::get<0>( repositories[0] );
|
||||
setRepositoryData( m_selectedRepositoryId );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_selectedRepositoryId = "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PCM::OnRefreshClicked( wxCommandEvent& event )
|
||||
{
|
||||
m_pcm->DiscardRepositoryCache( m_selectedRepositoryId );
|
||||
setRepositoryData( m_selectedRepositoryId );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PCM::OnInstallFromFileClicked( wxCommandEvent& event )
|
||||
{
|
||||
wxFileDialog open_file_dialog( this, _( "Choose package file" ), wxEmptyString, wxEmptyString,
|
||||
"Zip files (*.zip)|*.zip", wxFD_OPEN | wxFD_FILE_MUST_EXIST );
|
||||
|
||||
if( open_file_dialog.ShowModal() == wxID_CANCEL )
|
||||
return;
|
||||
|
||||
PCM_TASK_MANAGER task_manager( m_pcm );
|
||||
task_manager.InstallFromFile( this, open_file_dialog.GetPath() );
|
||||
|
||||
setInstalledPackages();
|
||||
|
||||
if( !m_selectedRepositoryId.IsEmpty() )
|
||||
setRepositoryData( m_selectedRepositoryId );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PCM::OnRepositoryChoice( wxCommandEvent& event )
|
||||
{
|
||||
wxStringClientData* data = static_cast<wxStringClientData*>(
|
||||
m_choiceRepository->GetClientObject( m_choiceRepository->GetSelection() ) );
|
||||
|
||||
m_selectedRepositoryId = data->GetData();
|
||||
|
||||
setRepositoryData( m_selectedRepositoryId );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PCM::setRepositoryData( const wxString& aRepositoryId )
|
||||
{
|
||||
if( m_pcm->CacheRepository( aRepositoryId ) )
|
||||
{
|
||||
for( const auto& entry : m_repositoryContentPanels )
|
||||
entry.second->ClearData();
|
||||
|
||||
m_packageBitmaps = m_pcm->GetRepositoryPackageBitmaps( aRepositoryId );
|
||||
|
||||
const std::vector<PCM_PACKAGE> packages = m_pcm->GetRepositoryPackages( aRepositoryId );
|
||||
|
||||
std::unordered_map<PCM_PACKAGE_TYPE, std::vector<PACKAGE_VIEW_DATA>> data;
|
||||
|
||||
for( const PCM_PACKAGE& pkg : packages )
|
||||
{
|
||||
PACKAGE_VIEW_DATA package_data( pkg );
|
||||
|
||||
if( m_packageBitmaps.count( package_data.package.identifier ) > 0 )
|
||||
package_data.bitmap = &m_packageBitmaps.at( package_data.package.identifier );
|
||||
else
|
||||
package_data.bitmap = &m_defaultBitmap;
|
||||
|
||||
package_data.state = m_pcm->GetPackageState( aRepositoryId, pkg.identifier );
|
||||
|
||||
for( const auto& action : m_pendingActions )
|
||||
{
|
||||
if( action.package.identifier != pkg.identifier )
|
||||
continue;
|
||||
|
||||
if( action.action == PPA_INSTALL )
|
||||
package_data.state = PPS_PENDING_INSTALL;
|
||||
else
|
||||
package_data.state = PPS_PENDING_UNINSTALL;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
package_data.repository_id = aRepositoryId;
|
||||
package_data.repository_name = m_choiceRepository->GetStringSelection();
|
||||
|
||||
data[pkg.type].emplace_back( package_data );
|
||||
}
|
||||
|
||||
for( size_t i = 0; i < PACKAGE_TYPE_LIST.size(); i++ )
|
||||
{
|
||||
PCM_PACKAGE_TYPE type = PACKAGE_TYPE_LIST[i].first;
|
||||
m_repositoryContentPanels[type]->SetData( data[type], m_callback );
|
||||
m_contentNotebook->SetPageText(
|
||||
i, wxString::Format( PACKAGE_TYPE_LIST[i].second, (int) data[type].size() ) );
|
||||
}
|
||||
|
||||
m_dialogNotebook->SetPageText(
|
||||
0, wxString::Format( _( "Repository (%d)" ), (int) packages.size() ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PCM::OnPendingActionsCellClicked( wxGridEvent& event )
|
||||
{
|
||||
m_gridPendingActions->ClearSelection();
|
||||
m_gridPendingActions->SelectRow( event.GetRow() );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PCM::updatePendingActionsTab()
|
||||
{
|
||||
m_dialogNotebook->SetPageText(
|
||||
2, wxString::Format( _( "Pending (%d)" ), (int) m_pendingActions.size() ) );
|
||||
|
||||
for( int col = 0; col < m_gridPendingActions->GetNumberCols(); col++ )
|
||||
{
|
||||
// Set the width to see the full contents
|
||||
m_gridPendingActions->SetColSize(
|
||||
col, m_gridPendingActions->GetVisibleWidth( col, true, true, false ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PCM::setInstalledPackages()
|
||||
{
|
||||
m_installedPanel->ClearData();
|
||||
|
||||
const std::vector<PCM_INSTALLATION_ENTRY> installed = m_pcm->GetInstalledPackages();
|
||||
std::vector<PACKAGE_VIEW_DATA> package_list;
|
||||
|
||||
m_installedBitmaps = m_pcm->GetInstalledPackageBitmaps();
|
||||
|
||||
for( const auto& entry : installed )
|
||||
{
|
||||
PACKAGE_VIEW_DATA package_data( entry );
|
||||
|
||||
if( m_installedBitmaps.count( package_data.package.identifier ) > 0 )
|
||||
package_data.bitmap = &m_installedBitmaps.at( package_data.package.identifier );
|
||||
else
|
||||
package_data.bitmap = &m_defaultBitmap;
|
||||
|
||||
package_list.emplace_back( package_data );
|
||||
}
|
||||
|
||||
m_installedPanel->SetData( package_list, m_callback );
|
||||
|
||||
m_dialogNotebook->SetPageText(
|
||||
1, wxString::Format( _( "Installed (%d)" ), (int) package_list.size() ) );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PCM::OnApplyChangesClicked( wxCommandEvent& event )
|
||||
{
|
||||
if( m_pendingActions.size() == 0 )
|
||||
return;
|
||||
|
||||
PCM_TASK_MANAGER task_manager( m_pcm );
|
||||
|
||||
for( const auto& action : m_pendingActions )
|
||||
{
|
||||
if( action.action == PPA_UNINSTALL )
|
||||
task_manager.Uninstall( action.package );
|
||||
else
|
||||
task_manager.DownloadAndInstall( action.package, action.version, action.repository_id );
|
||||
}
|
||||
|
||||
task_manager.RunQueue( this );
|
||||
|
||||
setInstalledPackages();
|
||||
wxCommandEvent dummy;
|
||||
OnDiscardChangesClicked( dummy );
|
||||
|
||||
if( !m_selectedRepositoryId.IsEmpty() )
|
||||
setRepositoryData( m_selectedRepositoryId );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PCM::OnDiscardChangesClicked( wxCommandEvent& event )
|
||||
{
|
||||
m_gridPendingActions->Freeze();
|
||||
|
||||
for( int i = m_pendingActions.size() - 1; i >= 0; i-- )
|
||||
discardAction( i );
|
||||
|
||||
updatePendingActionsTab();
|
||||
m_gridPendingActions->Thaw();
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PCM::OnDiscardActionClicked( wxCommandEvent& event )
|
||||
{
|
||||
wxArrayInt rows = m_gridPendingActions->GetSelectedRows();
|
||||
|
||||
std::sort( rows.begin(), rows.end(),
|
||||
[]( const int& a, const int& b )
|
||||
{
|
||||
return a > b;
|
||||
} );
|
||||
|
||||
m_gridPendingActions->Freeze();
|
||||
|
||||
for( int row : rows )
|
||||
discardAction( row );
|
||||
|
||||
updatePendingActionsTab();
|
||||
m_gridPendingActions->Thaw();
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PCM::discardAction( int aIndex )
|
||||
{
|
||||
m_gridPendingActions->DeleteRows( aIndex );
|
||||
|
||||
PENDING_ACTION action = m_pendingActions[aIndex];
|
||||
|
||||
PCM_PACKAGE_STATE state =
|
||||
m_pcm->GetPackageState( action.repository_id, action.package.identifier );
|
||||
|
||||
m_installedPanel->SetPackageState( action.package.identifier, state );
|
||||
|
||||
for( const auto& entry : m_repositoryContentPanels )
|
||||
entry.second->SetPackageState( action.package.identifier, state );
|
||||
|
||||
m_pendingActions.erase( m_pendingActions.begin() + aIndex );
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 Andrew Lutsenko, anlutsenko at gmail dot com
|
||||
* Copyright (C) 1992-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 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_PCM_H_
|
||||
#define DIALOG_PCM_H_
|
||||
|
||||
#include "core/wx_stl_compat.h"
|
||||
#include "dialog_pcm_base.h"
|
||||
#include "panel_package.h"
|
||||
#include "panel_packages_view.h"
|
||||
#include "pcm.h"
|
||||
#include "pcm_data.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
/** Implementing pcm main dialog. */
|
||||
class DIALOG_PCM : public DIALOG_PCM_BASE
|
||||
{
|
||||
public:
|
||||
/** Constructor */
|
||||
DIALOG_PCM( wxWindow* parent );
|
||||
~DIALOG_PCM();
|
||||
|
||||
///< Closes the window, asks user confirmation if there are pending actions
|
||||
void OnCloseClicked( wxCommandEvent& event ) override;
|
||||
|
||||
///< Opens repository management dialog, saves changes to PCM
|
||||
void OnManageRepositoriesClicked( wxCommandEvent& event ) override;
|
||||
|
||||
///< Discards current repo cache, fetches it anew and displays
|
||||
void OnRefreshClicked( wxCommandEvent& event ) override;
|
||||
|
||||
///< Opens file selection dialog and installs selected package archive
|
||||
void OnInstallFromFileClicked( wxCommandEvent& event ) override;
|
||||
|
||||
///< Enqueues current pending actions in PCM_TASK_MANAGER and runs the queue
|
||||
void OnApplyChangesClicked( wxCommandEvent& event ) override;
|
||||
|
||||
///< Discards all pending changes
|
||||
void OnDiscardChangesClicked( wxCommandEvent& event ) override;
|
||||
|
||||
///< Switches to another repository
|
||||
void OnRepositoryChoice( wxCommandEvent& event ) override;
|
||||
|
||||
///< Selects the whole row in the grid if a cell is clicked
|
||||
void OnPendingActionsCellClicked( wxGridEvent& event ) override;
|
||||
|
||||
///< Discards selected pending actions
|
||||
void OnDiscardActionClicked( wxCommandEvent& event ) override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Gets package data from PCM and displays it on repository tab
|
||||
*
|
||||
* @param aRepositoryId id of the repository
|
||||
*/
|
||||
void setRepositoryData( const wxString& aRepositoryId );
|
||||
|
||||
///< Sets repository choice list values
|
||||
void setRepositoryListFromPcm();
|
||||
|
||||
///< Updates pending actions tab caption and content-fits the grid
|
||||
void updatePendingActionsTab();
|
||||
|
||||
///< Gets installed packages list from PCM and displays it on installed tab
|
||||
void setInstalledPackages();
|
||||
|
||||
///< Discards specified pending action
|
||||
void discardAction( int aIndex );
|
||||
|
||||
std::shared_ptr<PLUGIN_CONTENT_MANAGER> m_pcm;
|
||||
ActionCallback m_callback;
|
||||
PANEL_PACKAGES_VIEW* m_installedPanel;
|
||||
std::unordered_map<PCM_PACKAGE_TYPE, PANEL_PACKAGES_VIEW*> m_repositoryContentPanels;
|
||||
wxString m_selectedRepositoryId;
|
||||
std::unordered_map<wxString, wxBitmap> m_packageBitmaps;
|
||||
std::unordered_map<wxString, wxBitmap> m_installedBitmaps;
|
||||
wxBitmap m_defaultBitmap;
|
||||
|
||||
struct PENDING_ACTION
|
||||
{
|
||||
PCM_PACKAGE_ACTION action;
|
||||
wxString repository_id;
|
||||
PCM_PACKAGE package;
|
||||
wxString version;
|
||||
PENDING_ACTION( const PCM_PACKAGE_ACTION& aAction, const wxString& aRepositoryId,
|
||||
const PCM_PACKAGE& aPackage, const wxString& aVersion ) :
|
||||
action( aAction ),
|
||||
repository_id( aRepositoryId ), package( aPackage ), version( aVersion )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<PENDING_ACTION> m_pendingActions;
|
||||
|
||||
enum PendingActionsGridColumns
|
||||
{
|
||||
PENDING_COL_ACTION = 0,
|
||||
PENDING_COL_NAME,
|
||||
PENDING_COL_VERSION,
|
||||
PENDING_COL_REPOSITORY
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#endif // DIALOG_PCM_H_
|
|
@ -0,0 +1,179 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Oct 26 2018)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "widgets/wx_grid.h"
|
||||
|
||||
#include "dialog_pcm_base.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DIALOG_PCM_BASE::DIALOG_PCM_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style )
|
||||
{
|
||||
this->SetSizeHints( wxSize( 650,500 ), wxDefaultSize );
|
||||
|
||||
wxBoxSizer* m_MainSizer;
|
||||
m_MainSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxBoxSizer* m_TopSizer;
|
||||
m_TopSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_dialogNotebook = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_panelRepository = new wxPanel( m_dialogNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
wxBoxSizer* bSizer4;
|
||||
bSizer4 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxBoxSizer* bSizer6;
|
||||
bSizer6 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
wxArrayString m_choiceRepositoryChoices;
|
||||
m_choiceRepository = new wxChoice( m_panelRepository, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceRepositoryChoices, 0 );
|
||||
m_choiceRepository->SetSelection( 0 );
|
||||
bSizer6->Add( m_choiceRepository, 1, wxALIGN_CENTER|wxALL, 5 );
|
||||
|
||||
m_buttonManage = new wxButton( m_panelRepository, wxID_ANY, _("Manage"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizer6->Add( m_buttonManage, 0, wxALL, 5 );
|
||||
|
||||
|
||||
bSizer4->Add( bSizer6, 0, wxEXPAND, 5 );
|
||||
|
||||
m_contentNotebook = new wxNotebook( m_panelRepository, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
|
||||
bSizer4->Add( m_contentNotebook, 1, wxEXPAND | wxALL, 5 );
|
||||
|
||||
|
||||
m_panelRepository->SetSizer( bSizer4 );
|
||||
m_panelRepository->Layout();
|
||||
bSizer4->Fit( m_panelRepository );
|
||||
m_dialogNotebook->AddPage( m_panelRepository, _("Repository (%d)"), false );
|
||||
m_panelInstalledHolder = new wxPanel( m_dialogNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
wxBoxSizer* bSizer7;
|
||||
bSizer7 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
|
||||
m_panelInstalledHolder->SetSizer( bSizer7 );
|
||||
m_panelInstalledHolder->Layout();
|
||||
bSizer7->Fit( m_panelInstalledHolder );
|
||||
m_dialogNotebook->AddPage( m_panelInstalledHolder, _("Installed (%d)"), false );
|
||||
m_panelPending = new wxPanel( m_dialogNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
m_panelPending->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
|
||||
m_panelPending->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
|
||||
|
||||
wxBoxSizer* bSizer8;
|
||||
bSizer8 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_gridPendingActions = new WX_GRID( m_panelPending, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
|
||||
// Grid
|
||||
m_gridPendingActions->CreateGrid( 0, 4 );
|
||||
m_gridPendingActions->EnableEditing( false );
|
||||
m_gridPendingActions->EnableGridLines( true );
|
||||
m_gridPendingActions->EnableDragGridSize( false );
|
||||
m_gridPendingActions->SetMargins( 0, 0 );
|
||||
|
||||
// Columns
|
||||
m_gridPendingActions->AutoSizeColumns();
|
||||
m_gridPendingActions->EnableDragColMove( false );
|
||||
m_gridPendingActions->EnableDragColSize( true );
|
||||
m_gridPendingActions->SetColLabelSize( 30 );
|
||||
m_gridPendingActions->SetColLabelValue( 0, _("Action") );
|
||||
m_gridPendingActions->SetColLabelValue( 1, _("Package") );
|
||||
m_gridPendingActions->SetColLabelValue( 2, _("Version") );
|
||||
m_gridPendingActions->SetColLabelValue( 3, _("Repository") );
|
||||
m_gridPendingActions->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
|
||||
|
||||
// Rows
|
||||
m_gridPendingActions->EnableDragRowSize( false );
|
||||
m_gridPendingActions->SetRowLabelSize( 0 );
|
||||
m_gridPendingActions->SetRowLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
|
||||
|
||||
// Label Appearance
|
||||
|
||||
// Cell Defaults
|
||||
m_gridPendingActions->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
|
||||
bSizer8->Add( m_gridPendingActions, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* bSizer9;
|
||||
bSizer9 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_discardActionButton = new wxBitmapButton( m_panelPending, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
|
||||
m_discardActionButton->SetToolTip( _("Discard action") );
|
||||
|
||||
bSizer9->Add( m_discardActionButton, 0, wxLEFT|wxRIGHT, 5 );
|
||||
|
||||
|
||||
bSizer9->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizer8->Add( bSizer9, 0, wxEXPAND, 0 );
|
||||
|
||||
|
||||
m_panelPending->SetSizer( bSizer8 );
|
||||
m_panelPending->Layout();
|
||||
bSizer8->Fit( m_panelPending );
|
||||
m_dialogNotebook->AddPage( m_panelPending, _("Pending (%d)"), true );
|
||||
|
||||
m_TopSizer->Add( m_dialogNotebook, 1, wxEXPAND | wxALL, 5 );
|
||||
|
||||
|
||||
m_MainSizer->Add( m_TopSizer, 1, wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* m_BottomSizer;
|
||||
m_BottomSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_refreshButton = new wxButton( this, wxID_ANY, _("Refresh"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_BottomSizer->Add( m_refreshButton, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_BottomSizer->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
m_installLocalButton = new wxButton( this, wxID_ANY, _("Install from file..."), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_BottomSizer->Add( m_installLocalButton, 0, wxALL, 5 );
|
||||
|
||||
m_applyButton = new wxButton( this, wxID_ANY, _("Apply changes"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_BottomSizer->Add( m_applyButton, 0, wxALL, 5 );
|
||||
|
||||
m_discardButton = new wxButton( this, wxID_ANY, _("Discard changes"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_BottomSizer->Add( m_discardButton, 0, wxALL, 5 );
|
||||
|
||||
m_closeButton = new wxButton( this, wxID_CANCEL, _("Close"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_BottomSizer->Add( m_closeButton, 0, wxALL, 5 );
|
||||
|
||||
|
||||
m_MainSizer->Add( m_BottomSizer, 0, wxEXPAND, 5 );
|
||||
|
||||
|
||||
this->SetSizer( m_MainSizer );
|
||||
this->Layout();
|
||||
|
||||
this->Centre( wxBOTH );
|
||||
|
||||
// Connect Events
|
||||
m_choiceRepository->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PCM_BASE::OnRepositoryChoice ), NULL, this );
|
||||
m_buttonManage->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PCM_BASE::OnManageRepositoriesClicked ), NULL, this );
|
||||
m_gridPendingActions->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_PCM_BASE::OnPendingActionsCellClicked ), NULL, this );
|
||||
m_discardActionButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PCM_BASE::OnDiscardActionClicked ), NULL, this );
|
||||
m_refreshButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PCM_BASE::OnRefreshClicked ), NULL, this );
|
||||
m_installLocalButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PCM_BASE::OnInstallFromFileClicked ), NULL, this );
|
||||
m_applyButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PCM_BASE::OnApplyChangesClicked ), NULL, this );
|
||||
m_discardButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PCM_BASE::OnDiscardChangesClicked ), NULL, this );
|
||||
m_closeButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PCM_BASE::OnCloseClicked ), NULL, this );
|
||||
}
|
||||
|
||||
DIALOG_PCM_BASE::~DIALOG_PCM_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
m_choiceRepository->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_PCM_BASE::OnRepositoryChoice ), NULL, this );
|
||||
m_buttonManage->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PCM_BASE::OnManageRepositoriesClicked ), NULL, this );
|
||||
m_gridPendingActions->Disconnect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_PCM_BASE::OnPendingActionsCellClicked ), NULL, this );
|
||||
m_discardActionButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PCM_BASE::OnDiscardActionClicked ), NULL, this );
|
||||
m_refreshButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PCM_BASE::OnRefreshClicked ), NULL, this );
|
||||
m_installLocalButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PCM_BASE::OnInstallFromFileClicked ), NULL, this );
|
||||
m_applyButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PCM_BASE::OnApplyChangesClicked ), NULL, this );
|
||||
m_discardButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PCM_BASE::OnDiscardChangesClicked ), NULL, this );
|
||||
m_closeButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PCM_BASE::OnCloseClicked ), NULL, this );
|
||||
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Oct 26 2018)
|
||||
// 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 WX_GRID;
|
||||
|
||||
#include "dialog_shim.h"
|
||||
#include <wx/string.h>
|
||||
#include <wx/choice.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/font.h>
|
||||
#include <wx/colour.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/icon.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/grid.h>
|
||||
#include <wx/bmpbuttn.h>
|
||||
#include <wx/dialog.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class DIALOG_PCM_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class DIALOG_PCM_BASE : public DIALOG_SHIM
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxNotebook* m_dialogNotebook;
|
||||
wxPanel* m_panelRepository;
|
||||
wxChoice* m_choiceRepository;
|
||||
wxButton* m_buttonManage;
|
||||
wxNotebook* m_contentNotebook;
|
||||
wxPanel* m_panelInstalledHolder;
|
||||
wxPanel* m_panelPending;
|
||||
WX_GRID* m_gridPendingActions;
|
||||
wxBitmapButton* m_discardActionButton;
|
||||
wxButton* m_refreshButton;
|
||||
wxButton* m_installLocalButton;
|
||||
wxButton* m_applyButton;
|
||||
wxButton* m_discardButton;
|
||||
wxButton* m_closeButton;
|
||||
|
||||
// Virtual event handlers, overide them in your derived class
|
||||
virtual void OnRepositoryChoice( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnManageRepositoriesClicked( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnPendingActionsCellClicked( wxGridEvent& event ) { event.Skip(); }
|
||||
virtual void OnDiscardActionClicked( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnRefreshClicked( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnInstallFromFileClicked( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnApplyChangesClicked( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnDiscardChangesClicked( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnCloseClicked( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
DIALOG_PCM_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Plugin And Content Manager"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 860,620 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
|
||||
~DIALOG_PCM_BASE();
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 Andrew Lutsenko, anlutsenko at gmail dot com
|
||||
* Copyright (C) 1992-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 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dialog_pcm_progress.h"
|
||||
#include <wx/msgdlg.h>
|
||||
|
||||
|
||||
#define GAUGE_RANGE 1000
|
||||
|
||||
DIALOG_PCM_PROGRESS::DIALOG_PCM_PROGRESS( wxWindow* parent, bool aShowDownloadSection ) :
|
||||
DIALOG_PCM_PROGRESS_BASE( parent )
|
||||
#if wxCHECK_VERSION( 3, 1, 0 )
|
||||
,
|
||||
m_appProgressIndicator( parent->GetParent(), GAUGE_RANGE )
|
||||
#endif
|
||||
{
|
||||
#if wxCHECK_VERSION( 3, 1, 0 )
|
||||
m_appProgressIndicator.Pulse();
|
||||
#endif
|
||||
m_cancelled.store( false );
|
||||
|
||||
m_reporter->SetImmediateMode();
|
||||
m_downloadGauge->SetRange( GAUGE_RANGE );
|
||||
m_overallGauge->SetRange( GAUGE_RANGE );
|
||||
|
||||
m_overallPhases = 1;
|
||||
|
||||
if( !aShowDownloadSection )
|
||||
m_panelDownload->Hide();
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PCM_PROGRESS::OnCancelClicked( wxCommandEvent& event )
|
||||
{
|
||||
m_cancelled.store( true );
|
||||
m_buttonCancel->Disable();
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PCM_PROGRESS::OnCloseClicked( wxCommandEvent& event )
|
||||
{
|
||||
EndModal( wxID_OK );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PCM_PROGRESS::Report( const wxString& aText, SEVERITY aSeverity )
|
||||
{
|
||||
CallAfter(
|
||||
[=]
|
||||
{
|
||||
m_reporter->Report( aText, aSeverity );
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PCM_PROGRESS::SetDownloadProgress( uint64_t aDownloaded, uint64_t aTotal )
|
||||
{
|
||||
if( aDownloaded > aTotal )
|
||||
aDownloaded = aTotal;
|
||||
|
||||
int value = 0;
|
||||
|
||||
if( aTotal > 0 )
|
||||
value = aDownloaded * GAUGE_RANGE / aTotal;
|
||||
|
||||
CallAfter(
|
||||
[=]
|
||||
{
|
||||
m_downloadText->SetLabel( wxString::Format( _( "Downloaded %lld/%lld Kb" ),
|
||||
toKb( aDownloaded ), toKb( aTotal ) ) );
|
||||
|
||||
m_downloadGauge->SetValue( value );
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
uint64_t DIALOG_PCM_PROGRESS::toKb( uint64_t aValue )
|
||||
{
|
||||
return ( aValue + 1023 ) / 1024;
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PCM_PROGRESS::SetOverallProgress( uint64_t aProgress, uint64_t aTotal )
|
||||
{
|
||||
double current = ( m_currentPhase + aProgress / (double) aTotal ) / m_overallPhases;
|
||||
|
||||
if( current > 1.0 )
|
||||
current = 1.0;
|
||||
|
||||
int value = current * GAUGE_RANGE;
|
||||
|
||||
CallAfter(
|
||||
[=]
|
||||
{
|
||||
m_overallGauge->SetValue( value );
|
||||
#if wxCHECK_VERSION( 3, 1, 0 )
|
||||
m_appProgressIndicator.SetValue( value );
|
||||
#endif
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PCM_PROGRESS::SetOverallProgressPhases( int aPhases )
|
||||
{
|
||||
m_currentPhase = 0;
|
||||
m_overallPhases = aPhases;
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PCM_PROGRESS::AdvanceOverallProgressPhase()
|
||||
{
|
||||
m_currentPhase++;
|
||||
SetOverallProgress( 0, 1 );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PCM_PROGRESS::SetFinished()
|
||||
{
|
||||
CallAfter(
|
||||
[this]
|
||||
{
|
||||
m_buttonCancel->Disable();
|
||||
m_buttonClose->Enable();
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PCM_PROGRESS::SetDownloadsFinished()
|
||||
{
|
||||
CallAfter(
|
||||
[this]
|
||||
{
|
||||
m_downloadText->SetLabel( _( "All downloads finished" ) );
|
||||
} );
|
||||
}
|
||||
|
||||
bool DIALOG_PCM_PROGRESS::IsCancelled()
|
||||
{
|
||||
return m_cancelled.load();
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 Andrew Lutsenko, anlutsenko at gmail dot com
|
||||
* Copyright (C) 1992-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 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_PCM_PROGRESS_H_
|
||||
#define DIALOG_PCM_PROGRESS_H_
|
||||
|
||||
|
||||
#include "dialog_pcm_progress_base.h"
|
||||
#include "reporter.h"
|
||||
#include <atomic>
|
||||
#if wxCHECK_VERSION( 3, 1, 0 )
|
||||
#include <wx/appprogress.h>
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief Progress dialog for PCM system
|
||||
*
|
||||
* This dialog is designed to work with PCM_TASK_MANAGER's threading system.
|
||||
* Some of it's methods are safe to call from a non-UI thread.
|
||||
*
|
||||
* SetOverallProgress(), SetOverallProgressPhases() and AdvanceOverallProgressPhase()
|
||||
* are meant to be called from the same thread.
|
||||
*/
|
||||
class DIALOG_PCM_PROGRESS : public DIALOG_PCM_PROGRESS_BASE
|
||||
{
|
||||
protected:
|
||||
// Handlers for DIALOG_PCM_PROGRESS_BASE events.
|
||||
void OnCancelClicked( wxCommandEvent& event ) override;
|
||||
void OnCloseClicked( wxCommandEvent& event ) override;
|
||||
|
||||
public:
|
||||
/** Constructor */
|
||||
DIALOG_PCM_PROGRESS( wxWindow* parent, bool aShowDownloadSection = true );
|
||||
|
||||
///< Thread safe. Adds a message to detailed report window.
|
||||
void Report( const wxString& aText, SEVERITY aSeverity = RPT_SEVERITY_UNDEFINED );
|
||||
|
||||
///< Thread safe. Sets current download progress gauge and text.
|
||||
void SetDownloadProgress( uint64_t aDownloaded, uint64_t aTotal );
|
||||
|
||||
///< Safe to call from non-UI thread. Sets current overall progress gauge.
|
||||
void SetOverallProgress( uint64_t aProgress, uint64_t aTotal );
|
||||
|
||||
///< Safe to call from non-UI thread. Sets number of phases for overall progress gauge.
|
||||
void SetOverallProgressPhases( int aPhases );
|
||||
|
||||
///< Safe to call from non-UI thread. Increments current phase by one.
|
||||
void AdvanceOverallProgressPhase();
|
||||
|
||||
///< Thread safe. Updates download text.
|
||||
void SetDownloadsFinished();
|
||||
|
||||
///< Thread safe. Disables cancel button, enables close button.
|
||||
void SetFinished();
|
||||
|
||||
///< Thread safe. Return true if cancel was clicked.
|
||||
bool IsCancelled();
|
||||
|
||||
private:
|
||||
static uint64_t toKb( uint64_t aValue );
|
||||
int m_currentPhase;
|
||||
int m_overallPhases;
|
||||
std::atomic_bool m_cancelled;
|
||||
#if wxCHECK_VERSION( 3, 1, 0 )
|
||||
wxAppProgressIndicator m_appProgressIndicator;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // DIALOG_PCM_PROGRESS_H_
|
|
@ -0,0 +1,100 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Oct 26 2018)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "dialog_pcm_progress_base.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DIALOG_PCM_PROGRESS_BASE::DIALOG_PCM_PROGRESS_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
|
||||
{
|
||||
this->SetSizeHints( wxSize( 400,300 ), wxDefaultSize );
|
||||
|
||||
wxBoxSizer* bSizer1;
|
||||
bSizer1 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_panelDownload = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
wxStaticBoxSizer* sbSizer1;
|
||||
sbSizer1 = new wxStaticBoxSizer( new wxStaticBox( m_panelDownload, wxID_ANY, _("Download progress") ), wxVERTICAL );
|
||||
|
||||
m_downloadText = new wxStaticText( sbSizer1->GetStaticBox(), wxID_ANY, _("Waiting..."), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_downloadText->Wrap( -1 );
|
||||
sbSizer1->Add( m_downloadText, 0, wxALL, 5 );
|
||||
|
||||
m_downloadGauge = new wxGauge( sbSizer1->GetStaticBox(), wxID_ANY, 100, wxDefaultPosition, wxDefaultSize, wxGA_HORIZONTAL|wxGA_SMOOTH );
|
||||
m_downloadGauge->SetValue( 0 );
|
||||
sbSizer1->Add( m_downloadGauge, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_panelDownload->SetSizer( sbSizer1 );
|
||||
m_panelDownload->Layout();
|
||||
sbSizer1->Fit( m_panelDownload );
|
||||
bSizer1->Add( m_panelDownload, 0, wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 5 );
|
||||
|
||||
m_panel2 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
wxBoxSizer* bSizer3;
|
||||
bSizer3 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxStaticBoxSizer* sbSizer2;
|
||||
sbSizer2 = new wxStaticBoxSizer( new wxStaticBox( m_panel2, wxID_ANY, _("Overall progress") ), wxVERTICAL );
|
||||
|
||||
m_overallGauge = new wxGauge( sbSizer2->GetStaticBox(), wxID_ANY, 100, wxDefaultPosition, wxDefaultSize, wxGA_HORIZONTAL );
|
||||
m_overallGauge->SetValue( 0 );
|
||||
sbSizer2->Add( m_overallGauge, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizer3->Add( sbSizer2, 0, wxEXPAND, 5 );
|
||||
|
||||
wxStaticBoxSizer* sbSizer3;
|
||||
sbSizer3 = new wxStaticBoxSizer( new wxStaticBox( m_panel2, wxID_ANY, _("Details") ), wxVERTICAL );
|
||||
|
||||
m_reporter = new WX_HTML_REPORT_BOX( sbSizer3->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxSize( -1,200 ), wxHW_SCROLLBAR_AUTO );
|
||||
sbSizer3->Add( m_reporter, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizer3->Add( sbSizer3, 1, wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* bSizer2;
|
||||
bSizer2 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
|
||||
bSizer2->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
m_buttonCancel = new wxButton( m_panel2, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizer2->Add( m_buttonCancel, 0, wxALL, 5 );
|
||||
|
||||
m_buttonClose = new wxButton( m_panel2, wxID_OK, _("Close"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
|
||||
m_buttonClose->SetDefault();
|
||||
m_buttonClose->Enable( false );
|
||||
|
||||
bSizer2->Add( m_buttonClose, 0, wxALL, 5 );
|
||||
|
||||
|
||||
bSizer3->Add( bSizer2, 0, wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_panel2->SetSizer( bSizer3 );
|
||||
m_panel2->Layout();
|
||||
bSizer3->Fit( m_panel2 );
|
||||
bSizer1->Add( m_panel2, 1, wxEXPAND | wxALL, 5 );
|
||||
|
||||
|
||||
this->SetSizer( bSizer1 );
|
||||
this->Layout();
|
||||
|
||||
// Connect Events
|
||||
m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PCM_PROGRESS_BASE::OnCancelClicked ), NULL, this );
|
||||
m_buttonClose->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PCM_PROGRESS_BASE::OnCloseClicked ), NULL, this );
|
||||
}
|
||||
|
||||
DIALOG_PCM_PROGRESS_BASE::~DIALOG_PCM_PROGRESS_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
m_buttonCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PCM_PROGRESS_BASE::OnCancelClicked ), NULL, this );
|
||||
m_buttonClose->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PCM_PROGRESS_BASE::OnCloseClicked ), NULL, this );
|
||||
|
||||
}
|
|
@ -0,0 +1,635 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
<wxFormBuilder_Project>
|
||||
<FileVersion major="1" minor="15" />
|
||||
<object class="Project" expanded="1">
|
||||
<property name="class_decoration">; </property>
|
||||
<property name="code_generation">C++</property>
|
||||
<property name="disconnect_events">1</property>
|
||||
<property name="disconnect_mode">source_name</property>
|
||||
<property name="disconnect_php_events">0</property>
|
||||
<property name="disconnect_python_events">0</property>
|
||||
<property name="embedded_files_path">res</property>
|
||||
<property name="encoding">UTF-8</property>
|
||||
<property name="event_generation">connect</property>
|
||||
<property name="file">dialog_pcm_progress_base</property>
|
||||
<property name="first_id">1000</property>
|
||||
<property name="help_provider">none</property>
|
||||
<property name="indent_with_spaces"></property>
|
||||
<property name="internationalize">1</property>
|
||||
<property name="name">dialog_pcm_progress_base</property>
|
||||
<property name="namespace"></property>
|
||||
<property name="path">.</property>
|
||||
<property name="precompiled_header"></property>
|
||||
<property name="relative_path">1</property>
|
||||
<property name="skip_lua_events">1</property>
|
||||
<property name="skip_php_events">1</property>
|
||||
<property name="skip_python_events">1</property>
|
||||
<property name="ui_table">UI</property>
|
||||
<property name="use_enum">0</property>
|
||||
<property name="use_microsoft_bom">0</property>
|
||||
<object class="Dialog" expanded="1">
|
||||
<property name="aui_managed">0</property>
|
||||
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
|
||||
<property name="bg"></property>
|
||||
<property name="center"></property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="event_handler">impl_virtual</property>
|
||||
<property name="extra_style"></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">400,300</property>
|
||||
<property name="name">DIALOG_PCM_PROGRESS_BASE</property>
|
||||
<property name="pos"></property>
|
||||
<property name="size">500,500</property>
|
||||
<property name="style">wxCAPTION</property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="title">Applying package changes</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bSizer1</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND|wxLEFT|wxRIGHT|wxTOP</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxPanel" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="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_panelDownload</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="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">wxTAB_TRAVERSAL</property>
|
||||
<object class="wxStaticBoxSizer" expanded="1">
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Download progress</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">sbSizer1</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="parent">1</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticText" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="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">Waiting...</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_downloadText</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"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<property name="wrap">-1</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL|wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxGauge" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="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_downloadGauge</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="range">100</property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style">wxGA_HORIZONTAL|wxGA_SMOOTH</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="value">0</property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND | wxALL</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxPanel" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="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_panel2</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="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">wxTAB_TRAVERSAL</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bSizer3</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticBoxSizer" expanded="1">
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Overall progress</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">sbSizer2</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="parent">1</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL|wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxGauge" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="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_overallGauge</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="range">100</property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style">wxGA_HORIZONTAL</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="value">0</property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxStaticBoxSizer" expanded="1">
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Details</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">sbSizer3</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="parent">1</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL|wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxHtmlWindow" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="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_reporter</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">-1,200</property>
|
||||
<property name="style">wxHW_SCROLLBAR_AUTO</property>
|
||||
<property name="subclass">WX_HTML_REPORT_BOX; dialogs/wx_html_report_box.h; Not 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>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bSizer2</property>
|
||||
<property name="orient">wxHORIZONTAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="spacer" expanded="1">
|
||||
<property name="height">0</property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="width">0</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxButton" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="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_CANCEL</property>
|
||||
<property name="label">Cancel</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_buttonCancel</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">OnCancelClicked</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxButton" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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">1</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="enabled">0</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_OK</property>
|
||||
<property name="label">Close</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_buttonClose</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">OnCloseClicked</event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</wxFormBuilder_Project>
|
|
@ -0,0 +1,62 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Oct 26 2018)
|
||||
// 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>
|
||||
#include "dialogs/wx_html_report_box.h"
|
||||
#include <wx/string.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/font.h>
|
||||
#include <wx/colour.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/gauge.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/statbox.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/html/htmlwin.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/icon.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/dialog.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class DIALOG_PCM_PROGRESS_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class DIALOG_PCM_PROGRESS_BASE : public wxDialog
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxPanel* m_panelDownload;
|
||||
wxStaticText* m_downloadText;
|
||||
wxGauge* m_downloadGauge;
|
||||
wxPanel* m_panel2;
|
||||
wxGauge* m_overallGauge;
|
||||
WX_HTML_REPORT_BOX* m_reporter;
|
||||
wxButton* m_buttonCancel;
|
||||
wxButton* m_buttonClose;
|
||||
|
||||
// Virtual event handlers, overide them in your derived class
|
||||
virtual void OnCancelClicked( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnCloseClicked( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
DIALOG_PCM_PROGRESS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Applying package changes"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 500,500 ), long style = wxCAPTION );
|
||||
~DIALOG_PCM_PROGRESS_BASE();
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 Andrew Lutsenko, anlutsenko at gmail dot com
|
||||
* Copyright (C) 1992-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 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/dcclient.h>
|
||||
|
||||
#include "panel_package.h"
|
||||
|
||||
PANEL_PACKAGE::PANEL_PACKAGE( wxWindow* parent, const ActionCallback& aCallback,
|
||||
const PACKAGE_VIEW_DATA& aData ) :
|
||||
PANEL_PACKAGE_BASE( parent ),
|
||||
m_actionCallback( aCallback ), m_data( aData )
|
||||
{
|
||||
// Propagate clicks on static elements to the panel handler.
|
||||
m_name->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( PANEL_PACKAGE::OnClick ), NULL, this );
|
||||
m_desc->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( PANEL_PACKAGE::OnClick ), NULL, this );
|
||||
m_bitmap->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( PANEL_PACKAGE::OnClick ), NULL, this );
|
||||
|
||||
wxColour bgColor = wxSystemSettings::GetColour( wxSYS_COLOUR_FRAMEBK );
|
||||
m_desc->SetBackgroundColour( bgColor );
|
||||
m_name->SetBackgroundColour( bgColor );
|
||||
m_bitmap->SetBackgroundColour( bgColor );
|
||||
|
||||
m_name->SetLabel( m_data.package.name );
|
||||
m_bitmap->SetBitmap( *m_data.bitmap );
|
||||
|
||||
// Set min width to 0 otherwise wxStaticLabel really doesn't want to shrink on resize
|
||||
m_desc->SetMinSize( wxSize( 0, -1 ) );
|
||||
|
||||
Layout();
|
||||
|
||||
m_desc->SetLabel( m_data.package.description );
|
||||
m_desc->Wrap( m_desc->GetClientSize().GetWidth() );
|
||||
|
||||
SetState( m_data.state );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PACKAGE::OnSize( wxSizeEvent& event )
|
||||
{
|
||||
Layout();
|
||||
m_desc->SetLabel( m_data.package.description );
|
||||
m_desc->Wrap( m_desc->GetClientSize().GetWidth() );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PACKAGE::SetState( PCM_PACKAGE_STATE aState )
|
||||
{
|
||||
m_data.state = aState;
|
||||
|
||||
switch( aState )
|
||||
{
|
||||
case PCM_PACKAGE_STATE::PPS_AVAILABLE:
|
||||
m_button->SetLabel( _( "Install" ) );
|
||||
m_button->Enable();
|
||||
break;
|
||||
case PCM_PACKAGE_STATE::PPS_UNAVAILABLE:
|
||||
m_button->SetLabel( _( "Install" ) );
|
||||
m_button->Disable();
|
||||
break;
|
||||
case PCM_PACKAGE_STATE::PPS_INSTALLED:
|
||||
m_button->SetLabel( _( "Uninstall" ) );
|
||||
m_button->Enable();
|
||||
break;
|
||||
case PCM_PACKAGE_STATE::PPS_PENDING_INSTALL:
|
||||
m_button->SetLabel( _( "Pending install" ) );
|
||||
m_button->Disable();
|
||||
break;
|
||||
case PCM_PACKAGE_STATE::PPS_PENDING_UNINSTALL:
|
||||
m_button->SetLabel( _( "Pending uninstall" ) );
|
||||
m_button->Disable();
|
||||
break;
|
||||
}
|
||||
|
||||
// Relayout to change button size to fit the label.
|
||||
wxSizeEvent dummy;
|
||||
OnSize( dummy );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PACKAGE::OnButtonClicked( wxCommandEvent& event )
|
||||
{
|
||||
// Versions are already presorted in descending order
|
||||
if( m_data.state == PPS_AVAILABLE )
|
||||
{
|
||||
// Find last stable compatible version
|
||||
auto ver_it = std::find_if( m_data.package.versions.begin(), m_data.package.versions.end(),
|
||||
[]( const PACKAGE_VERSION& ver )
|
||||
{
|
||||
return ver.compatible && ver.status == PVS_STABLE;
|
||||
} );
|
||||
|
||||
// If not found then find any compatible version
|
||||
if( ver_it == m_data.package.versions.end() )
|
||||
ver_it = std::find_if( m_data.package.versions.begin(), m_data.package.versions.end(),
|
||||
[]( const PACKAGE_VERSION& ver )
|
||||
{
|
||||
return ver.compatible;
|
||||
} );
|
||||
|
||||
if( ver_it == m_data.package.versions.end() )
|
||||
return; // Shouldn't happen
|
||||
|
||||
m_actionCallback( m_data, PPA_INSTALL, ver_it->version );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_actionCallback( m_data, PPA_UNINSTALL, m_data.current_version );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PACKAGE::SetSelectCallback( const std::function<void()>& aCallback )
|
||||
{
|
||||
m_selectCallback = aCallback;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PACKAGE::OnClick( wxMouseEvent& event )
|
||||
{
|
||||
m_selectCallback();
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PACKAGE::OnPaint( wxPaintEvent& event )
|
||||
{
|
||||
wxPaintDC dc( this );
|
||||
dc.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_FRAMEBK ) );
|
||||
dc.SetPen( wxPen( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ), 1 ) );
|
||||
|
||||
if( m_selected )
|
||||
dc.SetPen( wxPen( *wxBLACK, 3 ) );
|
||||
|
||||
dc.DrawRectangle( wxPoint( 0, 0 ), GetClientSize() );
|
||||
|
||||
if( !m_selected )
|
||||
dc.DrawLine( 0, 0, GetClientSize().GetX(), 0 );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PACKAGE::SetSelected( bool aSelected )
|
||||
{
|
||||
m_selected = aSelected;
|
||||
Refresh();
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 Andrew Lutsenko, anlutsenko at gmail dot com
|
||||
* Copyright (C) 1992-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 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 PANEL_PACKAGE_H_
|
||||
#define PANEL_PACKAGE_H_
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "panel_package_base.h"
|
||||
#include "pcm.h"
|
||||
|
||||
///< Collection of data relevant to the package display panel
|
||||
struct PACKAGE_VIEW_DATA
|
||||
{
|
||||
const PCM_PACKAGE package;
|
||||
wxBitmap* bitmap;
|
||||
PCM_PACKAGE_STATE state;
|
||||
wxString repository_id;
|
||||
wxString repository_name;
|
||||
wxString current_version;
|
||||
PACKAGE_VIEW_DATA( const PCM_PACKAGE aPackage ) : package( std::move( aPackage ) ){};
|
||||
PACKAGE_VIEW_DATA( const PCM_INSTALLATION_ENTRY& aEntry ) :
|
||||
package( std::move( aEntry.package ) )
|
||||
{
|
||||
state = PPS_INSTALLED;
|
||||
repository_id = aEntry.repository_id;
|
||||
repository_name = aEntry.repository_name;
|
||||
current_version = aEntry.current_version;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///< Callback for (un)install button
|
||||
using ActionCallback = std::function<void( const PACKAGE_VIEW_DATA& aData,
|
||||
PCM_PACKAGE_ACTION aAction, const wxString& aVersion )>;
|
||||
|
||||
|
||||
class PANEL_PACKAGE : public PANEL_PACKAGE_BASE
|
||||
{
|
||||
public:
|
||||
PANEL_PACKAGE( wxWindow* parent, const ActionCallback& aCallback,
|
||||
const PACKAGE_VIEW_DATA& aData );
|
||||
|
||||
///< Sets callback for OnClick action
|
||||
void SetSelectCallback( const std::function<void()>& aCallback );
|
||||
|
||||
///< Marks panel as selected
|
||||
void SetSelected( bool aSelected );
|
||||
|
||||
void OnButtonClicked( wxCommandEvent& event ) override;
|
||||
|
||||
///< Changes state of the (un)install button
|
||||
void SetState( PCM_PACKAGE_STATE aState );
|
||||
|
||||
///< Called when anywhere on the panel is clicked (except install button)
|
||||
void OnClick( wxMouseEvent& event ) override;
|
||||
|
||||
void OnSize( wxSizeEvent& event ) override;
|
||||
|
||||
const PACKAGE_VIEW_DATA& GetPackageData() const { return m_data; };
|
||||
|
||||
private:
|
||||
void OnPaint( wxPaintEvent& event ) override;
|
||||
std::function<void()> m_selectCallback;
|
||||
bool m_selected = false;
|
||||
const ActionCallback& m_actionCallback;
|
||||
PACKAGE_VIEW_DATA m_data;
|
||||
};
|
||||
|
||||
|
||||
#endif // PANEL_PACKAGE_H_
|
|
@ -0,0 +1,98 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Oct 26 2018)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "panel_package_base.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PANEL_PACKAGE_BASE::PANEL_PACKAGE_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
|
||||
{
|
||||
wxBoxSizer* bSizer1;
|
||||
bSizer1 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
wxBoxSizer* bSizer5;
|
||||
bSizer5 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
bSizer5->SetMinSize( wxSize( 70,-1 ) );
|
||||
|
||||
bSizer5->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* bSizer6;
|
||||
bSizer6 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
|
||||
bSizer6->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
m_bitmap = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizer6->Add( m_bitmap, 0, wxALL, 5 );
|
||||
|
||||
|
||||
bSizer6->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizer5->Add( bSizer6, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizer5->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizer1->Add( bSizer5, 0, wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* bSizer2;
|
||||
bSizer2 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_name = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END );
|
||||
m_name->Wrap( -1 );
|
||||
m_name->SetFont( wxFont( 12, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
|
||||
|
||||
bSizer2->Add( m_name, 0, wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 5 );
|
||||
|
||||
wxBoxSizer* bSizer3;
|
||||
bSizer3 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_desc = new wxStaticText( this, wxID_ANY, _("MyLabel"), wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END|wxST_NO_AUTORESIZE );
|
||||
m_desc->Wrap( -1 );
|
||||
bSizer3->Add( m_desc, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* bSizer4;
|
||||
bSizer4 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
|
||||
bSizer4->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
m_button = new wxButton( this, wxID_ANY, _("Install"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizer4->Add( m_button, 0, wxALL, 5 );
|
||||
|
||||
|
||||
bSizer3->Add( bSizer4, 0, wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizer2->Add( bSizer3, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizer1->Add( bSizer2, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
this->SetSizer( bSizer1 );
|
||||
this->Layout();
|
||||
|
||||
// Connect Events
|
||||
this->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( PANEL_PACKAGE_BASE::OnClick ) );
|
||||
this->Connect( wxEVT_PAINT, wxPaintEventHandler( PANEL_PACKAGE_BASE::OnPaint ) );
|
||||
this->Connect( wxEVT_SIZE, wxSizeEventHandler( PANEL_PACKAGE_BASE::OnSize ) );
|
||||
m_button->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PACKAGE_BASE::OnButtonClicked ), NULL, this );
|
||||
}
|
||||
|
||||
PANEL_PACKAGE_BASE::~PANEL_PACKAGE_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
this->Disconnect( wxEVT_LEFT_DOWN, wxMouseEventHandler( PANEL_PACKAGE_BASE::OnClick ) );
|
||||
this->Disconnect( wxEVT_PAINT, wxPaintEventHandler( PANEL_PACKAGE_BASE::OnPaint ) );
|
||||
this->Disconnect( wxEVT_SIZE, wxSizeEventHandler( PANEL_PACKAGE_BASE::OnSize ) );
|
||||
m_button->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PACKAGE_BASE::OnButtonClicked ), NULL, this );
|
||||
|
||||
}
|
|
@ -0,0 +1,421 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
<wxFormBuilder_Project>
|
||||
<FileVersion major="1" minor="15" />
|
||||
<object class="Project" expanded="1">
|
||||
<property name="class_decoration">; </property>
|
||||
<property name="code_generation">C++</property>
|
||||
<property name="disconnect_events">1</property>
|
||||
<property name="disconnect_mode">source_name</property>
|
||||
<property name="disconnect_php_events">0</property>
|
||||
<property name="disconnect_python_events">0</property>
|
||||
<property name="embedded_files_path"></property>
|
||||
<property name="encoding">UTF-8</property>
|
||||
<property name="event_generation">connect</property>
|
||||
<property name="file">panel_package_base</property>
|
||||
<property name="first_id">1000</property>
|
||||
<property name="help_provider">none</property>
|
||||
<property name="indent_with_spaces"></property>
|
||||
<property name="internationalize">1</property>
|
||||
<property name="name">panel_package_base</property>
|
||||
<property name="namespace"></property>
|
||||
<property name="path">./</property>
|
||||
<property name="precompiled_header"></property>
|
||||
<property name="relative_path">1</property>
|
||||
<property name="skip_lua_events">1</property>
|
||||
<property name="skip_php_events">1</property>
|
||||
<property name="skip_python_events">1</property>
|
||||
<property name="ui_table">UI</property>
|
||||
<property name="use_enum">0</property>
|
||||
<property name="use_microsoft_bom">0</property>
|
||||
<object class="Panel" expanded="1">
|
||||
<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="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"></property>
|
||||
<property name="name">PANEL_PACKAGE_BASE</property>
|
||||
<property name="pos"></property>
|
||||
<property name="size">-1,84</property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style">wxBORDER_NONE|wxTAB_TRAVERSAL</property>
|
||||
<event name="OnLeftDown">OnClick</event>
|
||||
<event name="OnPaint">OnPaint</event>
|
||||
<event name="OnSize">OnSize</event>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bSizer1</property>
|
||||
<property name="orient">wxHORIZONTAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size">70,-1</property>
|
||||
<property name="name">bSizer5</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="spacer" expanded="1">
|
||||
<property name="height">0</property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="width">0</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bSizer6</property>
|
||||
<property name="orient">wxHORIZONTAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="spacer" expanded="1">
|
||||
<property name="height">0</property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="width">0</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticBitmap" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</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_bitmap</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="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="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="spacer" expanded="1">
|
||||
<property name="height">0</property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="width">0</property>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="spacer" expanded="1">
|
||||
<property name="height">0</property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="width">0</property>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bSizer2</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND|wxLEFT|wxRIGHT|wxTOP</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticText" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font">,90,92,12,70,0</property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label"></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_name</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">wxST_ELLIPSIZE_END</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>
|
||||
<property name="wrap">-1</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bSizer3</property>
|
||||
<property name="orient">wxHORIZONTAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL|wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxStaticText" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="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">MyLabel</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_desc</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">wxST_ELLIPSIZE_END|wxST_NO_AUTORESIZE</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>
|
||||
<property name="wrap">-1</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bSizer4</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="spacer" expanded="1">
|
||||
<property name="height">0</property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="width">0</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxButton" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="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">Install</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_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"></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">OnButtonClicked</event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</wxFormBuilder_Project>
|
|
@ -0,0 +1,56 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Oct 26 2018)
|
||||
// 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>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/icon.h>
|
||||
#include <wx/statbmp.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/font.h>
|
||||
#include <wx/colour.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/string.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/panel.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class PANEL_PACKAGE_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class PANEL_PACKAGE_BASE : public wxPanel
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxStaticBitmap* m_bitmap;
|
||||
wxStaticText* m_name;
|
||||
wxStaticText* m_desc;
|
||||
wxButton* m_button;
|
||||
|
||||
// Virtual event handlers, overide them in your derived class
|
||||
virtual void OnClick( wxMouseEvent& event ) { event.Skip(); }
|
||||
virtual void OnPaint( wxPaintEvent& event ) { event.Skip(); }
|
||||
virtual void OnSize( wxSizeEvent& event ) { event.Skip(); }
|
||||
virtual void OnButtonClicked( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
PANEL_PACKAGE_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,84 ), long style = wxBORDER_NONE|wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
|
||||
~PANEL_PACKAGE_BASE();
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,507 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 Andrew Lutsenko, anlutsenko at gmail dot com
|
||||
* Copyright (C) 1992-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 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 "panel_packages_view.h"
|
||||
#include "bitmaps.h"
|
||||
#include "grid_tricks.h"
|
||||
#include "kicad_settings.h"
|
||||
#include "pgm_base.h"
|
||||
#include "settings/settings_manager.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <fstream>
|
||||
#include <wx/filedlg.h>
|
||||
#include <wx/font.h>
|
||||
#include <wx/tokenzr.h>
|
||||
|
||||
|
||||
#define GRID_CELL_MARGIN 4
|
||||
|
||||
|
||||
std::unordered_map<PCM_PACKAGE_VERSION_STATUS, wxString> PANEL_PACKAGES_VIEW::STATUS_ENUM_TO_STR = {
|
||||
{ PVS_INVALID, "invalid" },
|
||||
{ PVS_STABLE, "stable" },
|
||||
{ PVS_TESTING, "testing" },
|
||||
{ PVS_DEVELOPMENT, "development" },
|
||||
{ PVS_DEPRECATED, "deprecated" }
|
||||
};
|
||||
|
||||
|
||||
PANEL_PACKAGES_VIEW::PANEL_PACKAGES_VIEW( wxWindow* parent,
|
||||
std::shared_ptr<PLUGIN_CONTENT_MANAGER> aPcm ) :
|
||||
PANEL_PACKAGES_VIEW_BASE( parent ),
|
||||
m_pcm( aPcm )
|
||||
{
|
||||
m_searchBitmap->SetBitmap( KiBitmap( BITMAPS::find, 24 ) );
|
||||
m_gridVersions->PushEventHandler( new GRID_TRICKS( m_gridVersions ) );
|
||||
|
||||
for( int col = 0; col < m_gridVersions->GetNumberCols(); col++ )
|
||||
{
|
||||
const wxString& heading = m_gridVersions->GetColLabelValue( col );
|
||||
int headingWidth = GetTextExtent( heading ).x + 2 * GRID_CELL_MARGIN;
|
||||
|
||||
// Set the minimal width to the column label size.
|
||||
m_gridVersions->SetColMinimalWidth( col, headingWidth );
|
||||
m_gridVersions->SetColSize( col,
|
||||
m_gridVersions->GetVisibleWidth( col, true, true, false ) );
|
||||
}
|
||||
|
||||
m_infoText->SetBackgroundColour( wxStaticText::GetClassDefaultAttributes().colBg );
|
||||
|
||||
// Try to disable the caret on platforms that show it even in read-only controls
|
||||
m_infoText->Bind( wxEVT_SET_FOCUS,
|
||||
[&]( wxFocusEvent& event )
|
||||
{
|
||||
wxCaret* caret = m_infoText->GetCaret();
|
||||
|
||||
if( caret )
|
||||
caret->Hide();
|
||||
} );
|
||||
|
||||
ClearData();
|
||||
}
|
||||
|
||||
|
||||
PANEL_PACKAGES_VIEW::~PANEL_PACKAGES_VIEW()
|
||||
{
|
||||
m_gridVersions->PopEventHandler( true );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PACKAGES_VIEW::ClearData()
|
||||
{
|
||||
unsetPackageDetails();
|
||||
|
||||
m_currentSelected = nullptr;
|
||||
m_packagePanels.clear();
|
||||
m_packageInitialOrder.clear();
|
||||
m_packageListWindow->GetSizer()->Clear( true ); // Delete panels
|
||||
m_packageListWindow->GetSizer()->FitInside( m_packageListWindow );
|
||||
m_packageListWindow->Layout();
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PACKAGES_VIEW::SetData( const std::vector<PACKAGE_VIEW_DATA>& aPackageData,
|
||||
ActionCallback aCallback )
|
||||
{
|
||||
m_actionCallback = aCallback;
|
||||
|
||||
ClearData();
|
||||
|
||||
wxSizer* sizer = m_packageListWindow->GetSizer();
|
||||
|
||||
for( const PACKAGE_VIEW_DATA& data : aPackageData )
|
||||
{
|
||||
PANEL_PACKAGE* package_panel =
|
||||
new PANEL_PACKAGE( m_packageListWindow, m_actionCallback, data );
|
||||
|
||||
package_panel->SetSelectCallback(
|
||||
[package_panel, this]()
|
||||
{
|
||||
if( m_currentSelected && m_currentSelected != package_panel )
|
||||
m_currentSelected->SetSelected( false );
|
||||
|
||||
package_panel->SetSelected( true );
|
||||
m_currentSelected = package_panel;
|
||||
setPackageDetails( package_panel->GetPackageData() );
|
||||
|
||||
Layout();
|
||||
} );
|
||||
|
||||
m_packagePanels.insert( { data.package.identifier, package_panel } );
|
||||
m_packageInitialOrder.push_back( data.package.identifier );
|
||||
}
|
||||
|
||||
updatePackageList();
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PACKAGES_VIEW::setPackageDetails( const PACKAGE_VIEW_DATA& aPackageData )
|
||||
{
|
||||
const PCM_PACKAGE& package = aPackageData.package;
|
||||
|
||||
// Details
|
||||
m_infoText->Clear();
|
||||
|
||||
m_infoText->BeginParagraphSpacing( 0, 30 );
|
||||
m_infoText->WriteText( package.description_full );
|
||||
m_infoText->Newline();
|
||||
m_infoText->EndParagraphSpacing();
|
||||
|
||||
m_infoText->BeginFontSize( floor( m_infoText->GetDefaultStyle().GetFontSize() * 1.1 ) );
|
||||
m_infoText->WriteText( _( "Metadata" ) );
|
||||
m_infoText->Newline();
|
||||
m_infoText->EndFontSize();
|
||||
|
||||
m_infoText->BeginParagraphSpacing( 0, 10 );
|
||||
m_infoText->BeginSymbolBullet( wxString::FromUTF8( u8"\u25CF" ), 30, 40 );
|
||||
m_infoText->WriteText(
|
||||
wxString::Format( _( "Package identifier: %s\n" ), package.identifier ) );
|
||||
m_infoText->WriteText( wxString::Format( _( "License: %s\n" ), package.license ) );
|
||||
|
||||
if( package.tags.size() > 0 )
|
||||
{
|
||||
wxString tags_str;
|
||||
|
||||
for( const wxString& tag : package.tags )
|
||||
{
|
||||
if( !tags_str.IsEmpty() )
|
||||
tags_str += ", ";
|
||||
|
||||
tags_str += tag;
|
||||
}
|
||||
|
||||
m_infoText->WriteText( wxString::Format( _( "Tags: %s\n" ), tags_str ) );
|
||||
}
|
||||
|
||||
const auto write_contact = [&]( const wxString& type, const PCM_CONTACT& contact )
|
||||
{
|
||||
m_infoText->WriteText( wxString::Format( "%s: %s\n", type, contact.name ) );
|
||||
|
||||
m_infoText->BeginLeftIndent( 60, 40 );
|
||||
|
||||
for( const auto& entry : contact.contact )
|
||||
m_infoText->WriteText( wxString::Format( "%s: %s\n", entry.first, entry.second ) );
|
||||
|
||||
m_infoText->EndLeftIndent();
|
||||
};
|
||||
|
||||
write_contact( _( "Author" ), package.author );
|
||||
|
||||
if( package.maintainer )
|
||||
write_contact( _( "Maintainer" ), package.maintainer.get() );
|
||||
|
||||
if( package.resources.size() > 0 )
|
||||
{
|
||||
m_infoText->WriteText( _( "Resources" ) );
|
||||
m_infoText->Newline();
|
||||
|
||||
m_infoText->BeginLeftIndent( 60, 40 );
|
||||
|
||||
for( const auto& entry : package.resources )
|
||||
{
|
||||
m_infoText->WriteText( wxString::Format( "%s: %s\n", entry.first, entry.second ) );
|
||||
}
|
||||
|
||||
m_infoText->EndLeftIndent();
|
||||
}
|
||||
|
||||
m_infoText->EndSymbolBullet();
|
||||
m_infoText->EndParagraphSpacing();
|
||||
|
||||
// Versions table
|
||||
m_gridVersions->Freeze();
|
||||
|
||||
if( m_gridVersions->GetNumberRows() != 0 )
|
||||
m_gridVersions->DeleteRows( 0, m_gridVersions->GetNumberRows() );
|
||||
|
||||
int row = 0;
|
||||
wxString current_version;
|
||||
|
||||
if( aPackageData.state == PPS_INSTALLED )
|
||||
current_version = m_pcm->GetInstalledPackageVersion( package.identifier );
|
||||
|
||||
wxFont bold_font = m_gridVersions->GetDefaultCellFont().Bold();
|
||||
|
||||
for( const PACKAGE_VERSION& version : package.versions )
|
||||
{
|
||||
if( !version.compatible && !m_showAllVersions->IsChecked() )
|
||||
continue;
|
||||
|
||||
m_gridVersions->InsertRows( row );
|
||||
|
||||
m_gridVersions->SetCellValue( row, COL_VERSION, version.version );
|
||||
m_gridVersions->SetCellValue( row, COL_DOWNLOAD_SIZE,
|
||||
toHumanReadableSize( version.download_size ) );
|
||||
m_gridVersions->SetCellValue( row, COL_INSTALL_SIZE,
|
||||
toHumanReadableSize( version.install_size ) );
|
||||
m_gridVersions->SetCellValue( row, COL_COMPATIBILITY,
|
||||
version.compatible ? wxT( "\u2714" ) : wxEmptyString );
|
||||
m_gridVersions->SetCellValue( row, COL_STATUS, STATUS_ENUM_TO_STR.at( version.status ) );
|
||||
|
||||
m_gridVersions->SetCellAlignment( row, COL_COMPATIBILITY, wxALIGN_CENTER, wxALIGN_CENTER );
|
||||
|
||||
if( current_version == version.version )
|
||||
{
|
||||
for( int col = 0; col < m_gridVersions->GetNumberCols(); col++ )
|
||||
m_gridVersions->SetCellFont( row, col, bold_font );
|
||||
}
|
||||
|
||||
row++;
|
||||
}
|
||||
|
||||
for( int col = 0; col < m_gridVersions->GetNumberCols(); col++ )
|
||||
{
|
||||
// Set the width to see the full contents
|
||||
m_gridVersions->SetColSize( col,
|
||||
m_gridVersions->GetVisibleWidth( col, true, true, false ) );
|
||||
}
|
||||
|
||||
m_gridVersions->Thaw();
|
||||
|
||||
if( aPackageData.state == PPS_AVAILABLE || aPackageData.state == PPS_UNAVAILABLE )
|
||||
m_buttonInstall->Enable();
|
||||
else
|
||||
m_buttonInstall->Disable();
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PACKAGES_VIEW::unsetPackageDetails()
|
||||
{
|
||||
m_infoText->ChangeValue( _( "Pick a package on the left panel to view it's description." ) );
|
||||
|
||||
m_gridVersions->Freeze();
|
||||
|
||||
if( m_gridVersions->GetNumberRows() > 0 )
|
||||
m_gridVersions->DeleteRows( 0, m_gridVersions->GetNumberRows() );
|
||||
|
||||
m_gridVersions->Thaw();
|
||||
}
|
||||
|
||||
|
||||
wxString PANEL_PACKAGES_VIEW::toHumanReadableSize( const boost::optional<uint64_t> size ) const
|
||||
{
|
||||
if( !size )
|
||||
return "-";
|
||||
|
||||
uint64_t b = size.get();
|
||||
|
||||
if( b >= 1024 * 1024 )
|
||||
return wxString::Format( "%.1f Mb", b / 1024.0 / 1024.0 );
|
||||
|
||||
if( b >= 1024 )
|
||||
return wxString::Format( "%lld Kb", b / 1024 );
|
||||
|
||||
return wxString::Format( "%lld b", b );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PACKAGES_VIEW::SetPackageState( const wxString& aPackageId,
|
||||
const PCM_PACKAGE_STATE aState ) const
|
||||
{
|
||||
auto it = m_packagePanels.find( aPackageId );
|
||||
|
||||
if( it != m_packagePanels.end() )
|
||||
{
|
||||
it->second->SetState( aState );
|
||||
|
||||
if( m_currentSelected && m_currentSelected == it->second )
|
||||
{
|
||||
wxMouseEvent dummy;
|
||||
m_currentSelected->OnClick( dummy );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PACKAGES_VIEW::OnVersionsCellClicked( wxGridEvent& event )
|
||||
{
|
||||
m_gridVersions->ClearSelection();
|
||||
m_gridVersions->SelectRow( event.GetRow() );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PACKAGES_VIEW::OnDownloadVersionClicked( wxCommandEvent& event )
|
||||
{
|
||||
const auto rows = m_gridVersions->GetSelectedRows();
|
||||
|
||||
if( !m_currentSelected || rows.size() != 1 )
|
||||
{
|
||||
wxBell();
|
||||
return;
|
||||
}
|
||||
|
||||
wxString version = m_gridVersions->GetCellValue( rows[0], COL_VERSION );
|
||||
const PCM_PACKAGE& package = m_currentSelected->GetPackageData().package;
|
||||
|
||||
auto ver_it = std::find_if( package.versions.begin(), package.versions.end(),
|
||||
[&]( const PACKAGE_VERSION& ver )
|
||||
{
|
||||
return ver.version == version;
|
||||
} );
|
||||
|
||||
wxASSERT_MSG( ver_it != package.versions.end(), "Could not find package version" );
|
||||
|
||||
if( !ver_it->download_url )
|
||||
{
|
||||
wxMessageBox( _( "Package download url is not specified" ),
|
||||
_( "Error downloading package" ), wxICON_INFORMATION | wxOK, this );
|
||||
return;
|
||||
}
|
||||
|
||||
const wxString& url = ver_it->download_url.get();
|
||||
|
||||
SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
|
||||
KICAD_SETTINGS* app_settings = mgr.GetAppSettings<KICAD_SETTINGS>();
|
||||
|
||||
wxFileDialog dialog( this, _( "Save package" ), app_settings->m_PcmLastDownloadDir,
|
||||
wxString::Format( "%s_v%s.zip", package.identifier, version ),
|
||||
"ZIP files (*.zip)|*.zip", wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
|
||||
|
||||
if( dialog.ShowModal() == wxID_CANCEL )
|
||||
return;
|
||||
|
||||
wxString path = dialog.GetPath();
|
||||
app_settings->m_PcmLastDownloadDir = wxPathOnly( path );
|
||||
|
||||
std::ofstream output( path.ToUTF8(), std::ios_base::binary );
|
||||
|
||||
bool success = m_pcm->DownloadToStream( url, &output, _( "Downloading package" ), 0 );
|
||||
|
||||
output.close();
|
||||
|
||||
if( success )
|
||||
{
|
||||
if( ver_it->download_sha256 )
|
||||
{
|
||||
std::ifstream stream( path.ToUTF8(), std::ios_base::binary );
|
||||
|
||||
bool matches = m_pcm->VerifyHash( stream, ver_it->download_sha256.get() );
|
||||
|
||||
stream.close();
|
||||
|
||||
if( !matches
|
||||
&& wxMessageBox(
|
||||
_( "Integrity of the downloaded package could not be verified, hash "
|
||||
"does not match. Are you sure you want to keep this file?" ),
|
||||
_( "Keep downloaded file" ), wxICON_EXCLAMATION | wxYES_NO, this )
|
||||
== wxNO )
|
||||
{
|
||||
wxRemoveFile( path );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( wxFileExists( path ) )
|
||||
wxRemoveFile( path );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PACKAGES_VIEW::OnInstallVersionClicked( wxCommandEvent& event )
|
||||
{
|
||||
const auto rows = m_gridVersions->GetSelectedRows();
|
||||
|
||||
if( m_currentSelected && rows.size() != 1 )
|
||||
{
|
||||
wxBell();
|
||||
return;
|
||||
}
|
||||
|
||||
wxString version = m_gridVersions->GetCellValue( rows[0], COL_VERSION );
|
||||
const PCM_PACKAGE& package = m_currentSelected->GetPackageData().package;
|
||||
|
||||
auto ver_it = std::find_if( package.versions.begin(), package.versions.end(),
|
||||
[&]( const PACKAGE_VERSION& ver )
|
||||
{
|
||||
return ver.version == version;
|
||||
} );
|
||||
|
||||
wxASSERT_MSG( ver_it != package.versions.end(), "Could not find package version" );
|
||||
|
||||
if( !ver_it->compatible
|
||||
&& wxMessageBox( _( "This package version is incompatible with your kicad version or "
|
||||
"platform. Are you sure you want to install it anyway?" ),
|
||||
_( "Install package" ), wxICON_EXCLAMATION | wxYES_NO, this )
|
||||
== wxNO )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_actionCallback( m_currentSelected->GetPackageData(), PPA_INSTALL, version );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PACKAGES_VIEW::OnShowAllVersionsClicked( wxCommandEvent& event )
|
||||
{
|
||||
if( m_currentSelected )
|
||||
{
|
||||
wxMouseEvent dummy;
|
||||
m_currentSelected->OnClick( dummy );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PACKAGES_VIEW::OnSearchTextChanged( wxCommandEvent& event )
|
||||
{
|
||||
unsetPackageDetails();
|
||||
|
||||
if( m_currentSelected )
|
||||
m_currentSelected->SetSelected( false );
|
||||
|
||||
m_currentSelected = nullptr;
|
||||
|
||||
updatePackageList();
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PACKAGES_VIEW::updatePackageList()
|
||||
{
|
||||
// Sort by descending rank, ascending index
|
||||
std::vector<std::pair<int, int>> package_ranks;
|
||||
|
||||
const wxString search_term = m_searchCtrl->GetValue().Trim();
|
||||
|
||||
for( size_t index = 0; index < m_packageInitialOrder.size(); index++ )
|
||||
{
|
||||
int rank = 1;
|
||||
const PCM_PACKAGE& pkg =
|
||||
m_packagePanels[m_packageInitialOrder[index]]->GetPackageData().package;
|
||||
|
||||
if( search_term.size() > 2 )
|
||||
rank = m_pcm->GetPackageSearchRank( pkg, search_term );
|
||||
|
||||
// Packages with no versions are delisted and should not be shown
|
||||
if( pkg.versions.size() == 0 )
|
||||
rank = 0;
|
||||
|
||||
package_ranks.emplace_back( rank, index );
|
||||
}
|
||||
|
||||
std::sort( package_ranks.begin(), package_ranks.end(),
|
||||
[]( const std::pair<int, int>& a, const std::pair<int, int>& b )
|
||||
{
|
||||
return a.first > b.first || ( a.first == b.first && a.second < b.second );
|
||||
} );
|
||||
|
||||
// Rearrange panels, hide ones with 0 rank
|
||||
wxSizer* sizer = m_packageListWindow->GetSizer();
|
||||
sizer->Clear( false ); // Don't delete panels
|
||||
|
||||
for( const auto& pair : package_ranks )
|
||||
{
|
||||
PANEL_PACKAGE* panel = m_packagePanels[m_packageInitialOrder[pair.second]];
|
||||
|
||||
if( pair.first > 0 )
|
||||
{
|
||||
sizer->Add( panel, 0, wxEXPAND );
|
||||
panel->Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
panel->Hide();
|
||||
}
|
||||
}
|
||||
|
||||
sizer->FitInside( m_packageListWindow );
|
||||
m_packageListWindow->SetScrollRate( 0, 15 );
|
||||
m_packageListWindow->Layout();
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 Andrew Lutsenko, anlutsenko at gmail dot com
|
||||
* Copyright (C) 1992-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 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 PANEL_PACKAGES_VIEW_H_
|
||||
#define PANEL_PACKAGES_VIEW_H_
|
||||
|
||||
#include "core/wx_stl_compat.h"
|
||||
#include "panel_package.h"
|
||||
#include "panel_packages_view_base.h"
|
||||
#include "pcm.h"
|
||||
#include "pcm_data.h"
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
|
||||
class PANEL_PACKAGES_VIEW : public PANEL_PACKAGES_VIEW_BASE
|
||||
{
|
||||
public:
|
||||
PANEL_PACKAGES_VIEW( wxWindow* parent, std::shared_ptr<PLUGIN_CONTENT_MANAGER> aPcm );
|
||||
~PANEL_PACKAGES_VIEW();
|
||||
|
||||
/**
|
||||
* @brief Recreates package panels and displays daya
|
||||
*
|
||||
* @param aPackageData list of package view data
|
||||
* @param aCallback (un)install button callback
|
||||
*/
|
||||
void SetData( const std::vector<PACKAGE_VIEW_DATA>& aPackageData, ActionCallback aCallback );
|
||||
|
||||
/**
|
||||
* @brief Set the state of package
|
||||
*
|
||||
* @param aPackageId id of the package
|
||||
* @param aState new state
|
||||
*/
|
||||
void SetPackageState( const wxString& aPackageId, const PCM_PACKAGE_STATE aState ) const;
|
||||
|
||||
///< Destroys package panels
|
||||
void ClearData();
|
||||
|
||||
///< Selects full row of the clicked cell
|
||||
void OnVersionsCellClicked( wxGridEvent& event ) override;
|
||||
|
||||
///< Opens file chooser dialog and downloads selected package version archive
|
||||
void OnDownloadVersionClicked( wxCommandEvent& event ) override;
|
||||
|
||||
///< Schedules installation of selected package version
|
||||
void OnInstallVersionClicked( wxCommandEvent& event ) override;
|
||||
|
||||
///< Shows all versions including incompatible ones
|
||||
void OnShowAllVersionsClicked( wxCommandEvent& event ) override;
|
||||
|
||||
///< Ranks packages for entered search term and rearranges/hides panels according to their rank
|
||||
void OnSearchTextChanged( wxCommandEvent& event ) override;
|
||||
|
||||
private:
|
||||
///< Updates package listing according to search term
|
||||
void updatePackageList();
|
||||
|
||||
///< Updates details panel
|
||||
void setPackageDetails( const PACKAGE_VIEW_DATA& aPackageData );
|
||||
|
||||
///< Clears details panel
|
||||
void unsetPackageDetails();
|
||||
|
||||
///< Bytes to Kb/Mb/Gb string or "-" if absent
|
||||
wxString toHumanReadableSize( const boost::optional<uint64_t> size ) const;
|
||||
|
||||
ActionCallback m_actionCallback;
|
||||
std::unordered_map<wxString, PANEL_PACKAGE*> m_packagePanels;
|
||||
std::vector<wxString> m_packageInitialOrder;
|
||||
PANEL_PACKAGE* m_currentSelected;
|
||||
std::shared_ptr<PLUGIN_CONTENT_MANAGER> m_pcm;
|
||||
|
||||
enum PACKAGE_VERSIONS_GRID_COLUMNS
|
||||
{
|
||||
COL_VERSION = 0,
|
||||
COL_DOWNLOAD_SIZE,
|
||||
COL_INSTALL_SIZE,
|
||||
COL_COMPATIBILITY,
|
||||
COL_STATUS
|
||||
};
|
||||
|
||||
static std::unordered_map<PCM_PACKAGE_VERSION_STATUS, wxString> STATUS_ENUM_TO_STR;
|
||||
};
|
||||
|
||||
#endif // PANEL_PACKAGES_VIEW_H_
|
|
@ -0,0 +1,153 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Oct 26 2018)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "panel_packages_view_base.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PANEL_PACKAGES_VIEW_BASE::PANEL_PACKAGES_VIEW_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
|
||||
{
|
||||
wxBoxSizer* bSizer1;
|
||||
bSizer1 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxBoxSizer* bSizer7;
|
||||
bSizer7 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_searchBitmap = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizer7->Add( m_searchBitmap, 0, wxALL, 5 );
|
||||
|
||||
m_searchCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizer7->Add( m_searchCtrl, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizer1->Add( bSizer7, 0, wxEXPAND, 5 );
|
||||
|
||||
m_splitter1 = new wxSplitterWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_3D );
|
||||
m_splitter1->SetSashGravity( 0.55 );
|
||||
m_splitter1->Connect( wxEVT_IDLE, wxIdleEventHandler( PANEL_PACKAGES_VIEW_BASE::m_splitter1OnIdle ), NULL, this );
|
||||
m_splitter1->SetMinimumPaneSize( 300 );
|
||||
|
||||
m_packageListWindow = new wxScrolledWindow( m_splitter1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxALWAYS_SHOW_SB|wxBORDER_SUNKEN|wxFULL_REPAINT_ON_RESIZE|wxVSCROLL );
|
||||
m_packageListWindow->SetScrollRate( 5, 5 );
|
||||
wxBoxSizer* bSizer2;
|
||||
bSizer2 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
|
||||
m_packageListWindow->SetSizer( bSizer2 );
|
||||
m_packageListWindow->Layout();
|
||||
bSizer2->Fit( m_packageListWindow );
|
||||
m_panelDetails = new wxPanel( m_splitter1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
wxBoxSizer* bSizer3;
|
||||
bSizer3 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_notebook = new wxNotebook( m_panelDetails, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_panelDescription = new wxPanel( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
wxBoxSizer* bSizer4;
|
||||
bSizer4 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_infoText = new wxRichTextCtrl( m_panelDescription, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_AUTO_URL|wxTE_READONLY|wxVSCROLL|wxHSCROLL|wxNO_BORDER|wxWANTS_CHARS );
|
||||
bSizer4->Add( m_infoText, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_panelDescription->SetSizer( bSizer4 );
|
||||
m_panelDescription->Layout();
|
||||
bSizer4->Fit( m_panelDescription );
|
||||
m_notebook->AddPage( m_panelDescription, _("Description"), true );
|
||||
m_panelVersions = new wxPanel( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
wxBoxSizer* bSizer5;
|
||||
bSizer5 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_showAllVersions = new wxCheckBox( m_panelVersions, wxID_ANY, _("Show all versions"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizer5->Add( m_showAllVersions, 0, wxALL, 5 );
|
||||
|
||||
m_gridVersions = new WX_GRID( m_panelVersions, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
|
||||
// Grid
|
||||
m_gridVersions->CreateGrid( 0, 5 );
|
||||
m_gridVersions->EnableEditing( false );
|
||||
m_gridVersions->EnableGridLines( true );
|
||||
m_gridVersions->EnableDragGridSize( false );
|
||||
m_gridVersions->SetMargins( 0, 0 );
|
||||
|
||||
// Columns
|
||||
m_gridVersions->AutoSizeColumns();
|
||||
m_gridVersions->EnableDragColMove( false );
|
||||
m_gridVersions->EnableDragColSize( true );
|
||||
m_gridVersions->SetColLabelSize( 30 );
|
||||
m_gridVersions->SetColLabelValue( 0, _("Version") );
|
||||
m_gridVersions->SetColLabelValue( 1, _("Dl Size") );
|
||||
m_gridVersions->SetColLabelValue( 2, _("Inst Size") );
|
||||
m_gridVersions->SetColLabelValue( 3, _("Comp") );
|
||||
m_gridVersions->SetColLabelValue( 4, _("Status") );
|
||||
m_gridVersions->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
|
||||
|
||||
// Rows
|
||||
m_gridVersions->EnableDragRowSize( false );
|
||||
m_gridVersions->SetRowLabelSize( 0 );
|
||||
m_gridVersions->SetRowLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
|
||||
|
||||
// Label Appearance
|
||||
|
||||
// Cell Defaults
|
||||
m_gridVersions->SetDefaultCellAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
|
||||
bSizer5->Add( m_gridVersions, 1, wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* bSizer6;
|
||||
bSizer6 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
|
||||
bSizer6->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
m_buttonDownload = new wxButton( m_panelVersions, wxID_ANY, _("Download"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizer6->Add( m_buttonDownload, 0, wxALL, 5 );
|
||||
|
||||
m_buttonInstall = new wxButton( m_panelVersions, wxID_ANY, _("Install"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizer6->Add( m_buttonInstall, 0, wxALL, 5 );
|
||||
|
||||
|
||||
bSizer6->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizer5->Add( bSizer6, 0, wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_panelVersions->SetSizer( bSizer5 );
|
||||
m_panelVersions->Layout();
|
||||
bSizer5->Fit( m_panelVersions );
|
||||
m_notebook->AddPage( m_panelVersions, _("Versions"), false );
|
||||
|
||||
bSizer3->Add( m_notebook, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
m_panelDetails->SetSizer( bSizer3 );
|
||||
m_panelDetails->Layout();
|
||||
bSizer3->Fit( m_panelDetails );
|
||||
m_splitter1->SplitVertically( m_packageListWindow, m_panelDetails, 0 );
|
||||
bSizer1->Add( m_splitter1, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
this->SetSizer( bSizer1 );
|
||||
this->Layout();
|
||||
|
||||
// Connect Events
|
||||
m_searchCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PACKAGES_VIEW_BASE::OnSearchTextChanged ), NULL, this );
|
||||
m_showAllVersions->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PANEL_PACKAGES_VIEW_BASE::OnShowAllVersionsClicked ), NULL, this );
|
||||
m_gridVersions->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( PANEL_PACKAGES_VIEW_BASE::OnVersionsCellClicked ), NULL, this );
|
||||
m_buttonDownload->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PACKAGES_VIEW_BASE::OnDownloadVersionClicked ), NULL, this );
|
||||
m_buttonInstall->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PACKAGES_VIEW_BASE::OnInstallVersionClicked ), NULL, this );
|
||||
}
|
||||
|
||||
PANEL_PACKAGES_VIEW_BASE::~PANEL_PACKAGES_VIEW_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
m_searchCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PACKAGES_VIEW_BASE::OnSearchTextChanged ), NULL, this );
|
||||
m_showAllVersions->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PANEL_PACKAGES_VIEW_BASE::OnShowAllVersionsClicked ), NULL, this );
|
||||
m_gridVersions->Disconnect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( PANEL_PACKAGES_VIEW_BASE::OnVersionsCellClicked ), NULL, this );
|
||||
m_buttonDownload->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PACKAGES_VIEW_BASE::OnDownloadVersionClicked ), NULL, this );
|
||||
m_buttonInstall->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PACKAGES_VIEW_BASE::OnInstallVersionClicked ), NULL, this );
|
||||
|
||||
}
|
|
@ -0,0 +1,957 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
<wxFormBuilder_Project>
|
||||
<FileVersion major="1" minor="15" />
|
||||
<object class="Project" expanded="1">
|
||||
<property name="class_decoration">; </property>
|
||||
<property name="code_generation">C++</property>
|
||||
<property name="disconnect_events">1</property>
|
||||
<property name="disconnect_mode">source_name</property>
|
||||
<property name="disconnect_php_events">0</property>
|
||||
<property name="disconnect_python_events">0</property>
|
||||
<property name="embedded_files_path"></property>
|
||||
<property name="encoding">UTF-8</property>
|
||||
<property name="event_generation">connect</property>
|
||||
<property name="file">panel_packages_view_base</property>
|
||||
<property name="first_id">1000</property>
|
||||
<property name="help_provider">none</property>
|
||||
<property name="indent_with_spaces"></property>
|
||||
<property name="internationalize">1</property>
|
||||
<property name="name">panel_packages_view_base</property>
|
||||
<property name="namespace"></property>
|
||||
<property name="path">./</property>
|
||||
<property name="precompiled_header"></property>
|
||||
<property name="relative_path">1</property>
|
||||
<property name="skip_lua_events">1</property>
|
||||
<property name="skip_php_events">1</property>
|
||||
<property name="skip_python_events">1</property>
|
||||
<property name="ui_table">UI</property>
|
||||
<property name="use_enum">0</property>
|
||||
<property name="use_microsoft_bom">0</property>
|
||||
<object class="Panel" expanded="1">
|
||||
<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="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"></property>
|
||||
<property name="name">PANEL_PACKAGES_VIEW_BASE</property>
|
||||
<property name="pos"></property>
|
||||
<property name="size">500,300</property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style">wxTAB_TRAVERSAL</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bSizer1</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bSizer7</property>
|
||||
<property name="orient">wxHORIZONTAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticBitmap" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</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_searchBitmap</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="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="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL|wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxTextCtrl" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="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="maxlength"></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_searchCtrl</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"></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="value"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnText">OnSearchTextChanged</event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxSplitterWindow" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="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_pane_size">300</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_splitter1</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="sashgravity">0.55</property>
|
||||
<property name="sashpos">0</property>
|
||||
<property name="sashsize">-1</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="splitmode">wxSPLIT_VERTICAL</property>
|
||||
<property name="style">wxSP_3D</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 class="splitteritem" expanded="1">
|
||||
<object class="wxScrolledWindow" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="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_packageListWindow</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="scroll_rate_x">5</property>
|
||||
<property name="scroll_rate_y">5</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></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">wxALWAYS_SHOW_SB|wxBORDER_SUNKEN|wxFULL_REPAINT_ON_RESIZE|wxVSCROLL</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bSizer2</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="splitteritem" expanded="1">
|
||||
<object class="wxPanel" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="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_panelDetails</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="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">wxTAB_TRAVERSAL</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bSizer3</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxNotebook" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="bitmapsize"></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="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_notebook</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"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<object class="notebookpage" expanded="1">
|
||||
<property name="bitmap"></property>
|
||||
<property name="label">Description</property>
|
||||
<property name="select">1</property>
|
||||
<object class="wxPanel" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="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_panelDescription</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="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">wxTAB_TRAVERSAL</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bSizer4</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxRichTextCtrl" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="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_infoText</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">wxTE_AUTO_URL|wxTE_READONLY</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">wxVSCROLL|wxHSCROLL|wxNO_BORDER|wxWANTS_CHARS</property>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="notebookpage" expanded="1">
|
||||
<property name="bitmap"></property>
|
||||
<property name="label">Versions</property>
|
||||
<property name="select">0</property>
|
||||
<object class="wxPanel" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="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_panelVersions</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="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">wxTAB_TRAVERSAL</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bSizer5</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxCheckBox" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="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">Show all versions</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_showAllVersions</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"></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="OnCheckBox">OnShowAllVersionsClicked</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxGrid" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="autosize_cols">1</property>
|
||||
<property name="autosize_rows">0</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_CENTER</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">30</property>
|
||||
<property name="col_label_values">"Version" "Dl Size" "Inst Size" "Comp" "Status"</property>
|
||||
<property name="col_label_vert_alignment">wxALIGN_CENTER</property>
|
||||
<property name="cols">5</property>
|
||||
<property name="column_sizes"></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_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">1</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"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_gridVersions</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="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">0</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="subclass">WX_GRID; widgets/wx_grid.h; Not 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="OnGridCellLeftClick">OnVersionsCellClicked</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">bSizer6</property>
|
||||
<property name="orient">wxHORIZONTAL</property>
|
||||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="spacer" expanded="1">
|
||||
<property name="height">0</property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="width">0</property>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxButton" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="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">Download</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_buttonDownload</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">OnDownloadVersionClicked</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxButton" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></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="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">Install</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_buttonInstall</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">OnInstallVersionClicked</event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="spacer" expanded="1">
|
||||
<property name="height">0</property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="width">0</property>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</wxFormBuilder_Project>
|
|
@ -0,0 +1,79 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Oct 26 2018)
|
||||
// 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>
|
||||
#include "widgets/wx_grid.h"
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/icon.h>
|
||||
#include <wx/statbmp.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/font.h>
|
||||
#include <wx/colour.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/string.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/scrolwin.h>
|
||||
#include <wx/richtext/richtextctrl.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/grid.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/splitter.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class PANEL_PACKAGES_VIEW_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class PANEL_PACKAGES_VIEW_BASE : public wxPanel
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxStaticBitmap* m_searchBitmap;
|
||||
wxTextCtrl* m_searchCtrl;
|
||||
wxSplitterWindow* m_splitter1;
|
||||
wxScrolledWindow* m_packageListWindow;
|
||||
wxPanel* m_panelDetails;
|
||||
wxNotebook* m_notebook;
|
||||
wxPanel* m_panelDescription;
|
||||
wxRichTextCtrl* m_infoText;
|
||||
wxPanel* m_panelVersions;
|
||||
wxCheckBox* m_showAllVersions;
|
||||
WX_GRID* m_gridVersions;
|
||||
wxButton* m_buttonDownload;
|
||||
wxButton* m_buttonInstall;
|
||||
|
||||
// Virtual event handlers, overide them in your derived class
|
||||
virtual void OnSearchTextChanged( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnShowAllVersionsClicked( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnVersionsCellClicked( wxGridEvent& event ) { event.Skip(); }
|
||||
virtual void OnDownloadVersionClicked( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnInstallVersionClicked( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
PANEL_PACKAGES_VIEW_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 500,300 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
|
||||
~PANEL_PACKAGES_VIEW_BASE();
|
||||
|
||||
void m_splitter1OnIdle( wxIdleEvent& )
|
||||
{
|
||||
m_splitter1->SetSashPosition( 0 );
|
||||
m_splitter1->Disconnect( wxEVT_IDLE, wxIdleEventHandler( PANEL_PACKAGES_VIEW_BASE::m_splitter1OnIdle ), NULL, this );
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,813 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 Andrew Lutsenko, anlutsenko at gmail dot com
|
||||
* Copyright (C) 1992-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 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 "pcm.h"
|
||||
#include "core/wx_stl_compat.h"
|
||||
#include "kicad_build_version.h"
|
||||
#include "kicad_curl/kicad_curl_easy.h"
|
||||
#include "paths.h"
|
||||
#include "pgm_base.h"
|
||||
#include "picosha2.h"
|
||||
#include "settings/settings_manager.h"
|
||||
#include "widgets/wx_progress_reporters.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <memory>
|
||||
#include <wx/dir.h>
|
||||
#include <wx/filefn.h>
|
||||
#include <wx/fs_zip.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/mstream.h>
|
||||
#include <wx/sstream.h>
|
||||
#include <wx/tokenzr.h>
|
||||
#include <wx/wfstream.h>
|
||||
#include <wx/zipstrm.h>
|
||||
|
||||
|
||||
const std::tuple<int, int> PLUGIN_CONTENT_MANAGER::m_kicad_version =
|
||||
KICAD_MAJOR_MINOR_VERSION_TUPLE;
|
||||
|
||||
|
||||
PLUGIN_CONTENT_MANAGER::PLUGIN_CONTENT_MANAGER( wxWindow* aParent ) : m_dialog( aParent )
|
||||
{
|
||||
// Get 3rd party path
|
||||
const ENV_VAR_MAP& env = Pgm().GetLocalEnvVariables();
|
||||
auto it = env.find( "KICAD6_3RD_PARTY" );
|
||||
|
||||
if( it != env.end() && !it->second.GetValue().IsEmpty() )
|
||||
m_3rdparty_path = it->second.GetValue();
|
||||
else
|
||||
m_3rdparty_path = PATHS::GetDefault3rdPartyPath();
|
||||
|
||||
// Read and store pcm schema
|
||||
wxFileName schema_file( PATHS::GetStockDataPath(), "pcm.v1.schema.json" );
|
||||
schema_file.AppendDir( "schemas" );
|
||||
|
||||
std::ifstream schema_stream( schema_file.GetFullPath().ToUTF8() );
|
||||
nlohmann::json schema;
|
||||
|
||||
try
|
||||
{
|
||||
schema_stream >> schema;
|
||||
m_schema_validator.set_root_schema( schema );
|
||||
}
|
||||
catch( std::exception& e )
|
||||
{
|
||||
wxLogError( wxString::Format( _( "Error loading schema: %s" ), e.what() ) );
|
||||
}
|
||||
|
||||
// Load currently installed packages
|
||||
wxFileName f( SETTINGS_MANAGER::GetUserSettingsPath(), "installed_packages.json" );
|
||||
|
||||
if( f.FileExists() )
|
||||
{
|
||||
std::ifstream installed_stream( f.GetFullPath().ToUTF8() );
|
||||
nlohmann::json installed;
|
||||
|
||||
try
|
||||
{
|
||||
installed_stream >> installed;
|
||||
|
||||
if( installed.contains( "packages" ) && installed["packages"].is_array() )
|
||||
{
|
||||
for( const auto& js_entry : installed["packages"] )
|
||||
{
|
||||
PCM_INSTALLATION_ENTRY entry = js_entry.get<PCM_INSTALLATION_ENTRY>();
|
||||
m_installed.emplace( entry.package.identifier, entry );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( std::exception& e )
|
||||
{
|
||||
wxLogError( wxString::Format( _( "Error loading installed packages list: %s" ),
|
||||
e.what() ) );
|
||||
}
|
||||
}
|
||||
|
||||
// As a fall back populate installed from names of directories
|
||||
|
||||
for( const wxString& dir : PCM_PACKAGE_DIRECTORIES )
|
||||
{
|
||||
wxFileName d( m_3rdparty_path, "" );
|
||||
d.AppendDir( dir );
|
||||
|
||||
if( d.DirExists() )
|
||||
{
|
||||
wxDir package_dir( d.GetPath() );
|
||||
|
||||
if( !package_dir.IsOpened() )
|
||||
continue;
|
||||
|
||||
wxString subdir;
|
||||
bool more = package_dir.GetFirst( &subdir, "", wxDIR_DIRS | wxDIR_HIDDEN );
|
||||
|
||||
while( more )
|
||||
{
|
||||
if( m_installed.find( subdir ) == m_installed.end() )
|
||||
{
|
||||
PCM_INSTALLATION_ENTRY entry;
|
||||
wxFileName subdir_file( d.GetPath(), subdir );
|
||||
|
||||
// wxFileModificationTime bugs out on windows for directories
|
||||
wxStructStat stat;
|
||||
wxStat( subdir_file.GetFullPath(), &stat );
|
||||
|
||||
entry.package.name = subdir;
|
||||
entry.package.identifier = subdir;
|
||||
entry.current_version = "0.0";
|
||||
entry.install_timestamp = stat.st_mtime;
|
||||
entry.repository_name = wxT( "<unknown>" );
|
||||
|
||||
m_installed.emplace( subdir, entry );
|
||||
}
|
||||
|
||||
more = package_dir.GetNext( &subdir );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate package compatibility
|
||||
std::for_each( m_installed.begin(), m_installed.end(),
|
||||
[&]( auto& entry )
|
||||
{
|
||||
preparePackage( entry.second.package );
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
bool PLUGIN_CONTENT_MANAGER::DownloadToStream( const wxString& aUrl, std::ostream* aOutput,
|
||||
const wxString& aDialogTitle,
|
||||
const size_t aSizeLimit )
|
||||
{
|
||||
bool size_exceeded = false;
|
||||
|
||||
std::unique_ptr<WX_PROGRESS_REPORTER> reporter(
|
||||
new WX_PROGRESS_REPORTER( m_dialog, aDialogTitle, 1 ) );
|
||||
|
||||
TRANSFER_CALLBACK callback = [&]( size_t dltotal, size_t dlnow, size_t ultotal, size_t ulnow )
|
||||
{
|
||||
if( aSizeLimit > 0 && ( dltotal > aSizeLimit || dlnow > aSizeLimit ) )
|
||||
{
|
||||
size_exceeded = true;
|
||||
// Non zero return means abort.
|
||||
return true;
|
||||
}
|
||||
|
||||
if( dltotal > 1024 )
|
||||
{
|
||||
reporter->SetCurrentProgress( dlnow / (double) dltotal );
|
||||
reporter->Report( wxString::Format( _( "Downloading %lld/%lld Kb" ), dlnow / 1024,
|
||||
dltotal / 1024 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
reporter->SetCurrentProgress( 0.0 );
|
||||
}
|
||||
return !reporter->KeepRefreshing();
|
||||
};
|
||||
|
||||
KICAD_CURL_EASY curl;
|
||||
curl.SetOutputStream( aOutput );
|
||||
curl.SetURL( aUrl.ToUTF8().data() );
|
||||
curl.SetFollowRedirects( true );
|
||||
curl.SetTransferCallback( callback, 250000L );
|
||||
|
||||
int code = curl.Perform();
|
||||
|
||||
if( !reporter->IsCancelled() )
|
||||
reporter->SetCurrentProgress( 1.0 );
|
||||
|
||||
if( code != CURLE_OK )
|
||||
{
|
||||
if( code == CURLE_ABORTED_BY_CALLBACK && size_exceeded )
|
||||
wxMessageBox( _( "Download is too large." ) );
|
||||
else if( code != CURLE_ABORTED_BY_CALLBACK )
|
||||
wxLogError( wxString( curl.GetErrorText( code ) ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PLUGIN_CONTENT_MANAGER::FetchRepository( const wxString& aUrl, PCM_REPOSITORY& aRepository )
|
||||
{
|
||||
std::stringstream repository_stream;
|
||||
if( !DownloadToStream( aUrl, &repository_stream, _( "Fetching repository" ), 20480 ) )
|
||||
{
|
||||
wxLogError( _( "Unable to load repository url" ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
nlohmann::json repository_json;
|
||||
try
|
||||
{
|
||||
repository_stream >> repository_json;
|
||||
|
||||
ValidateJson( repository_json, nlohmann::json_uri( "#/definitions/Repository" ) );
|
||||
|
||||
aRepository = repository_json.get<PCM_REPOSITORY>();
|
||||
}
|
||||
catch( const std::exception& e )
|
||||
{
|
||||
wxLogError( wxString::Format( _( "Unable to parse repository:\n\n%s" ), e.what() ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void PLUGIN_CONTENT_MANAGER::ValidateJson( const nlohmann::json& aJson,
|
||||
const nlohmann::json_uri& aUri ) const
|
||||
{
|
||||
nlohmann::json_schema::basic_error_handler error_handler;
|
||||
m_schema_validator.validate( aJson, error_handler, aUri );
|
||||
}
|
||||
|
||||
|
||||
bool PLUGIN_CONTENT_MANAGER::fetchPackages( const wxString& aUrl,
|
||||
const boost::optional<wxString>& aHash,
|
||||
std::vector<PCM_PACKAGE>& aPackages )
|
||||
{
|
||||
std::stringstream packages_stream;
|
||||
if( !DownloadToStream( aUrl, &packages_stream, _( "Fetching repository packages" ) ) )
|
||||
{
|
||||
wxLogError( _( "Unable to load repository packages url." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
std::istringstream isstream( packages_stream.str() );
|
||||
|
||||
if( aHash && !VerifyHash( isstream, aHash.get() ) )
|
||||
{
|
||||
wxLogError( _( "Packages hash doesn't match. Repository may be corrupted." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
nlohmann::json packages_json = nlohmann::json::parse( packages_stream.str() );
|
||||
ValidateJson( packages_json, nlohmann::json_uri( "#/definitions/PackageArray" ) );
|
||||
|
||||
for( nlohmann::json& package : packages_json["packages"] )
|
||||
{
|
||||
aPackages.push_back( package.get<PCM_PACKAGE>() );
|
||||
}
|
||||
}
|
||||
catch( std::exception& e )
|
||||
{
|
||||
wxLogError( wxString::Format( _( "Unable to parse packages metadata:\n\n%s" ), e.what() ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PLUGIN_CONTENT_MANAGER::VerifyHash( std::istream& aStream, const wxString& aHash ) const
|
||||
{
|
||||
std::vector<unsigned char> bytes( picosha2::k_digest_size );
|
||||
|
||||
picosha2::hash256( std::istreambuf_iterator<char>( aStream ), std::istreambuf_iterator<char>(),
|
||||
bytes.begin(), bytes.end() );
|
||||
std::string hex_str = picosha2::bytes_to_hex_string( bytes.begin(), bytes.end() );
|
||||
|
||||
return aHash.compare( hex_str ) == 0;
|
||||
}
|
||||
|
||||
|
||||
const PCM_REPOSITORY&
|
||||
PLUGIN_CONTENT_MANAGER::getCachedRepository( const wxString& aRepositoryId ) const
|
||||
{
|
||||
wxASSERT_MSG( m_repository_cache.find( aRepositoryId ) != m_repository_cache.end(),
|
||||
"Repository is not cached." );
|
||||
|
||||
return m_repository_cache.at( aRepositoryId );
|
||||
}
|
||||
|
||||
|
||||
const bool PLUGIN_CONTENT_MANAGER::CacheRepository( const wxString& aRepositoryId )
|
||||
{
|
||||
if( m_repository_cache.find( aRepositoryId ) != m_repository_cache.end() )
|
||||
return true;
|
||||
|
||||
const auto repository_tuple =
|
||||
std::find_if( m_repository_list.begin(), m_repository_list.end(),
|
||||
[&aRepositoryId]( const std::tuple<wxString, wxString, wxString>& t )
|
||||
{
|
||||
return std::get<0>( t ) == aRepositoryId;
|
||||
} );
|
||||
|
||||
if( repository_tuple == m_repository_list.end() )
|
||||
return false;
|
||||
|
||||
wxString url = std::get<2>( *repository_tuple );
|
||||
|
||||
nlohmann::json js;
|
||||
PCM_REPOSITORY current_repo;
|
||||
|
||||
if( !FetchRepository( url, current_repo ) )
|
||||
return false;
|
||||
|
||||
bool packages_cache_exists = false;
|
||||
|
||||
// First load repository data from local filesystem if available.
|
||||
wxFileName repo_cache = wxFileName( m_3rdparty_path, "repository.json" );
|
||||
repo_cache.AppendDir( "cache" );
|
||||
repo_cache.AppendDir( aRepositoryId );
|
||||
wxFileName packages_cache( repo_cache.GetPath(), "packages.json" );
|
||||
|
||||
if( repo_cache.FileExists() && packages_cache.FileExists() )
|
||||
{
|
||||
std::ifstream repo_stream( repo_cache.GetFullPath().ToUTF8() );
|
||||
repo_stream >> js;
|
||||
PCM_REPOSITORY saved_repo = js.get<PCM_REPOSITORY>();
|
||||
|
||||
if( saved_repo.packages.update_timestamp == current_repo.packages.update_timestamp )
|
||||
{
|
||||
// Cached repo is up to date, use data on disk
|
||||
js.clear();
|
||||
std::ifstream packages_cache_stream( packages_cache.GetFullPath().ToUTF8() );
|
||||
|
||||
try
|
||||
{
|
||||
packages_cache_stream >> js;
|
||||
saved_repo.package_list = js["packages"].get<std::vector<PCM_PACKAGE>>();
|
||||
|
||||
std::for_each( saved_repo.package_list.begin(), saved_repo.package_list.end(),
|
||||
&preparePackage );
|
||||
|
||||
m_repository_cache[aRepositoryId] = std::move( saved_repo );
|
||||
|
||||
packages_cache_exists = true;
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
wxLogError( _( "Packages cache for current repository is "
|
||||
"corrupted, it will be redownloaded." ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !packages_cache_exists )
|
||||
{
|
||||
// Cache doesn't exist or is out of date
|
||||
if( !fetchPackages( current_repo.packages.url, current_repo.packages.sha256,
|
||||
current_repo.package_list ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::for_each( current_repo.package_list.begin(), current_repo.package_list.end(),
|
||||
&preparePackage );
|
||||
|
||||
repo_cache.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
|
||||
|
||||
std::ofstream repo_cache_stream( repo_cache.GetFullPath().ToUTF8() );
|
||||
repo_cache_stream << std::setw( 4 ) << nlohmann::json( current_repo ) << std::endl;
|
||||
|
||||
std::ofstream packages_cache_stream( packages_cache.GetFullPath().ToUTF8() );
|
||||
js.clear();
|
||||
js["packages"] = nlohmann::json( current_repo.package_list );
|
||||
packages_cache_stream << std::setw( 4 ) << js << std::endl;
|
||||
|
||||
m_repository_cache[aRepositoryId] = std::move( current_repo );
|
||||
}
|
||||
|
||||
if( current_repo.resources )
|
||||
{
|
||||
// Check resources file date, redownload if needed
|
||||
PCM_RESOURCE_REFERENCE& resources = current_repo.resources.get();
|
||||
|
||||
wxFileName resource_file( repo_cache.GetPath(), "resources.zip" );
|
||||
|
||||
time_t mtime = 0;
|
||||
|
||||
if( resource_file.FileExists() )
|
||||
mtime = wxFileModificationTime( resource_file.GetFullPath() );
|
||||
|
||||
if( mtime + 600 < getCurrentTimestamp() && mtime < (time_t) resources.update_timestamp )
|
||||
{
|
||||
std::ofstream resources_stream( resource_file.GetFullPath().ToUTF8(),
|
||||
std::ios_base::binary );
|
||||
|
||||
// 100 Mb resource file limit
|
||||
bool success = DownloadToStream( resources.url, &resources_stream,
|
||||
_( "Downloading resources" ), 100 * 1024 * 1024 );
|
||||
|
||||
resources_stream.close();
|
||||
|
||||
if( success )
|
||||
{
|
||||
std::ifstream read_stream( resource_file.GetFullPath().ToUTF8(),
|
||||
std::ios_base::binary );
|
||||
|
||||
|
||||
if( resources.sha256 && !VerifyHash( read_stream, resources.sha256.get() ) )
|
||||
{
|
||||
read_stream.close();
|
||||
wxLogError(
|
||||
_( "Resources file hash doesn't match and will not be used. Repository "
|
||||
"may be corrupted." ) );
|
||||
wxRemoveFile( resource_file.GetFullPath() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not critical, just clean up the file
|
||||
wxRemoveFile( resource_file.GetFullPath() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void PLUGIN_CONTENT_MANAGER::preparePackage( PCM_PACKAGE& aPackage )
|
||||
{
|
||||
// Parse package version strings
|
||||
for( PACKAGE_VERSION& ver : aPackage.versions )
|
||||
{
|
||||
int epoch = 0, major = 0, minor = 0, patch = 0;
|
||||
|
||||
if( ver.version_epoch )
|
||||
epoch = ver.version_epoch.get();
|
||||
|
||||
wxStringTokenizer version_tokenizer( ver.version, "." );
|
||||
|
||||
major = wxAtoi( version_tokenizer.GetNextToken() );
|
||||
|
||||
if( version_tokenizer.HasMoreTokens() )
|
||||
minor = wxAtoi( version_tokenizer.GetNextToken() );
|
||||
|
||||
if( version_tokenizer.HasMoreTokens() )
|
||||
patch = wxAtoi( version_tokenizer.GetNextToken() );
|
||||
|
||||
ver.parsed_version = std::make_tuple( epoch, major, minor, patch );
|
||||
|
||||
// Determine compatibility
|
||||
ver.compatible = true;
|
||||
|
||||
auto parse_major_minor = []( const wxString& version )
|
||||
{
|
||||
wxStringTokenizer tokenizer( version, "." );
|
||||
int major = wxAtoi( tokenizer.GetNextToken() );
|
||||
int minor = wxAtoi( tokenizer.GetNextToken() );
|
||||
return std::tuple<int, int>( major, minor );
|
||||
};
|
||||
|
||||
if( parse_major_minor( ver.kicad_version ) > m_kicad_version )
|
||||
ver.compatible = false;
|
||||
|
||||
if( ver.kicad_version_max
|
||||
&& parse_major_minor( ver.kicad_version_max.get() ) < m_kicad_version )
|
||||
ver.compatible = false;
|
||||
|
||||
#ifdef __WXMSW__
|
||||
wxString platform = wxT( "windows" );
|
||||
#endif
|
||||
#ifdef __WXOSX__
|
||||
wxString platform = wxT( "macos" );
|
||||
#endif
|
||||
#ifdef __WXGTK__
|
||||
wxString platform = wxT( "linux" );
|
||||
#endif
|
||||
|
||||
if( ver.platforms.size() > 0
|
||||
&& std::find( ver.platforms.begin(), ver.platforms.end(), platform )
|
||||
== ver.platforms.end() )
|
||||
{
|
||||
ver.compatible = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by descending version
|
||||
std::sort( aPackage.versions.begin(), aPackage.versions.end(),
|
||||
[]( const PACKAGE_VERSION& a, const PACKAGE_VERSION& b )
|
||||
{
|
||||
return a.parsed_version > b.parsed_version;
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
const std::vector<PCM_PACKAGE>&
|
||||
PLUGIN_CONTENT_MANAGER::GetRepositoryPackages( const wxString& aRepositoryId ) const
|
||||
{
|
||||
return getCachedRepository( aRepositoryId ).package_list;
|
||||
}
|
||||
|
||||
|
||||
void PLUGIN_CONTENT_MANAGER::SetRepositoryList( const STRING_PAIR_LIST& aRepositories )
|
||||
{
|
||||
// Clean up cache folder if repository is not in new list
|
||||
for( const auto& entry : m_repository_list )
|
||||
{
|
||||
auto it = std::find_if( aRepositories.begin(), aRepositories.end(),
|
||||
[&]( const auto& new_entry )
|
||||
{
|
||||
return new_entry.first == std::get<1>( entry );
|
||||
} );
|
||||
|
||||
if( it == aRepositories.end() )
|
||||
{
|
||||
DiscardRepositoryCache( std::get<0>( entry ) );
|
||||
}
|
||||
}
|
||||
|
||||
m_repository_list.clear();
|
||||
m_repository_cache.clear();
|
||||
|
||||
for( const auto& repo : aRepositories )
|
||||
{
|
||||
std::string url_sha = picosha2::hash256_hex_string( repo.second );
|
||||
m_repository_list.push_back(
|
||||
std::make_tuple( url_sha.substr( 0, 16 ), repo.first, repo.second ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PLUGIN_CONTENT_MANAGER::DiscardRepositoryCache( const wxString& aRepositoryId )
|
||||
{
|
||||
if( m_repository_cache.count( aRepositoryId ) > 0 )
|
||||
m_repository_cache.erase( aRepositoryId );
|
||||
|
||||
wxFileName repo_cache( m_3rdparty_path, "" );
|
||||
repo_cache.AppendDir( "cache" );
|
||||
repo_cache.AppendDir( aRepositoryId );
|
||||
|
||||
if( repo_cache.DirExists() )
|
||||
repo_cache.Rmdir( wxPATH_RMDIR_RECURSIVE );
|
||||
}
|
||||
|
||||
|
||||
void PLUGIN_CONTENT_MANAGER::MarkInstalled( const PCM_PACKAGE& aPackage, const wxString& aVersion,
|
||||
const wxString& aRepositoryId )
|
||||
{
|
||||
PCM_INSTALLATION_ENTRY entry;
|
||||
entry.package = aPackage;
|
||||
entry.current_version = aVersion;
|
||||
entry.repository_id = aRepositoryId;
|
||||
|
||||
if( !aRepositoryId.IsEmpty() )
|
||||
entry.repository_name = getCachedRepository( aRepositoryId ).name;
|
||||
else
|
||||
entry.repository_name = _( "Local file" );
|
||||
|
||||
entry.install_timestamp = getCurrentTimestamp();
|
||||
|
||||
m_installed.emplace( aPackage.identifier, entry );
|
||||
}
|
||||
|
||||
|
||||
void PLUGIN_CONTENT_MANAGER::MarkUninstalled( const PCM_PACKAGE& aPackage )
|
||||
{
|
||||
m_installed.erase( aPackage.identifier );
|
||||
}
|
||||
|
||||
|
||||
PCM_PACKAGE_STATE PLUGIN_CONTENT_MANAGER::GetPackageState( const wxString& aRepositoryId,
|
||||
const wxString& aPackageId )
|
||||
{
|
||||
if( m_installed.find( aPackageId ) != m_installed.end() )
|
||||
return PPS_INSTALLED;
|
||||
|
||||
if( aRepositoryId.IsEmpty() || !CacheRepository( aRepositoryId ) )
|
||||
return PPS_UNAVAILABLE;
|
||||
|
||||
const PCM_REPOSITORY& repo = getCachedRepository( aRepositoryId );
|
||||
|
||||
auto pkg_it = std::find_if( repo.package_list.begin(), repo.package_list.end(),
|
||||
[&aPackageId]( const PCM_PACKAGE& pkg )
|
||||
{
|
||||
return pkg.identifier == aPackageId;
|
||||
} );
|
||||
|
||||
if( pkg_it == repo.package_list.end() )
|
||||
return PPS_UNAVAILABLE;
|
||||
|
||||
const PCM_PACKAGE& pkg = *pkg_it;
|
||||
|
||||
auto ver_it = std::find_if( pkg.versions.begin(), pkg.versions.end(),
|
||||
[]( const PACKAGE_VERSION& ver )
|
||||
{
|
||||
return ver.compatible;
|
||||
} );
|
||||
|
||||
if( ver_it == pkg.versions.end() )
|
||||
return PPS_UNAVAILABLE;
|
||||
else
|
||||
return PPS_AVAILABLE;
|
||||
}
|
||||
|
||||
|
||||
time_t PLUGIN_CONTENT_MANAGER::getCurrentTimestamp() const
|
||||
{
|
||||
return std::chrono::duration_cast<std::chrono::seconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch() )
|
||||
.count();
|
||||
}
|
||||
|
||||
|
||||
PLUGIN_CONTENT_MANAGER::~PLUGIN_CONTENT_MANAGER()
|
||||
{
|
||||
// Save current installed packages list.
|
||||
|
||||
nlohmann::json js;
|
||||
js["packages"] = nlohmann::json::array();
|
||||
|
||||
for( const auto& entry : m_installed )
|
||||
{
|
||||
js["packages"].emplace_back( entry.second );
|
||||
}
|
||||
|
||||
wxFileName f( SETTINGS_MANAGER::GetUserSettingsPath(), "installed_packages.json" );
|
||||
std::ofstream stream( f.GetFullPath().ToUTF8() );
|
||||
|
||||
stream << std::setw( 4 ) << js << std::endl;
|
||||
}
|
||||
|
||||
|
||||
const std::vector<PCM_INSTALLATION_ENTRY> PLUGIN_CONTENT_MANAGER::GetInstalledPackages() const
|
||||
{
|
||||
std::vector<PCM_INSTALLATION_ENTRY> v;
|
||||
|
||||
std::for_each( m_installed.begin(), m_installed.end(),
|
||||
[&v]( const auto& entry )
|
||||
{
|
||||
v.push_back( entry.second );
|
||||
} );
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
const wxString&
|
||||
PLUGIN_CONTENT_MANAGER::GetInstalledPackageVersion( const wxString& aPackageId ) const
|
||||
{
|
||||
wxASSERT_MSG( m_installed.find( aPackageId ) != m_installed.end(),
|
||||
"Installed package not found." );
|
||||
|
||||
return m_installed.at( aPackageId ).current_version;
|
||||
}
|
||||
|
||||
|
||||
int PLUGIN_CONTENT_MANAGER::GetPackageSearchRank( const PCM_PACKAGE& aPackage,
|
||||
const wxString& aSearchTerm )
|
||||
{
|
||||
wxArrayString terms = wxStringTokenize( aSearchTerm.Lower(), " ", wxTOKEN_STRTOK );
|
||||
int rank = 0;
|
||||
|
||||
const auto find_term_matches = [&]( const wxString& str )
|
||||
{
|
||||
int result = 0;
|
||||
wxString lower = str.Lower();
|
||||
|
||||
for( const wxString& term : terms )
|
||||
if( lower.Find( term ) != wxNOT_FOUND )
|
||||
result += 1;
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
// Match on package id
|
||||
if( terms.size() == 1 && terms[0] == aPackage.identifier )
|
||||
rank += 10000;
|
||||
|
||||
if( terms.size() == 1 && find_term_matches( aPackage.identifier ) )
|
||||
rank += 1000;
|
||||
|
||||
// Match on package name
|
||||
rank += 500 * find_term_matches( aPackage.name );
|
||||
|
||||
// Match on tags
|
||||
for( const wxString& tag : aPackage.tags )
|
||||
rank += 100 * find_term_matches( tag );
|
||||
|
||||
// Match on package description
|
||||
rank += 10 * find_term_matches( aPackage.description );
|
||||
rank += 10 * find_term_matches( aPackage.description_full );
|
||||
|
||||
// Match on author/maintainer
|
||||
rank += find_term_matches( aPackage.author.name );
|
||||
|
||||
if( aPackage.maintainer )
|
||||
rank += 3 * find_term_matches( aPackage.maintainer.get().name );
|
||||
|
||||
// Match on resources
|
||||
for( const auto& entry : aPackage.resources )
|
||||
{
|
||||
rank += find_term_matches( entry.first );
|
||||
rank += find_term_matches( entry.second );
|
||||
}
|
||||
|
||||
// Match on license
|
||||
if( terms.size() == 1 && terms[0] == aPackage.license )
|
||||
rank += 1;
|
||||
|
||||
return rank;
|
||||
}
|
||||
|
||||
|
||||
std::unordered_map<wxString, wxBitmap>
|
||||
PLUGIN_CONTENT_MANAGER::GetRepositoryPackageBitmaps( const wxString& aRepositoryId )
|
||||
{
|
||||
std::unordered_map<wxString, wxBitmap> bitmaps;
|
||||
|
||||
wxFileName resources_file = wxFileName( m_3rdparty_path, "resources.zip" );
|
||||
resources_file.AppendDir( "cache" );
|
||||
resources_file.AppendDir( aRepositoryId );
|
||||
|
||||
if( !resources_file.FileExists() )
|
||||
return bitmaps;
|
||||
|
||||
wxFFileInputStream stream( resources_file.GetFullPath() );
|
||||
wxZipInputStream zip( stream );
|
||||
|
||||
if( !zip.IsOk() || zip.GetTotalEntries() == 0 )
|
||||
return bitmaps;
|
||||
|
||||
for( wxArchiveEntry* entry = zip.GetNextEntry(); entry; entry = zip.GetNextEntry() )
|
||||
{
|
||||
wxArrayString path_parts =
|
||||
wxSplit( entry->GetName(), wxFileName::GetPathSeparator(), (wxChar) NULL );
|
||||
|
||||
if( path_parts.size() != 2 || path_parts[1] != "icon.png" )
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
wxMemoryInputStream image_stream( zip, entry->GetSize() );
|
||||
wxImage image( image_stream, wxBITMAP_TYPE_PNG );
|
||||
bitmaps.emplace( path_parts[0], wxBitmap( image ) );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
// Log and ignore
|
||||
wxLogTrace( "Error loading png bitmap for entry %s from %s", entry->GetName(),
|
||||
resources_file.GetFullPath() );
|
||||
}
|
||||
}
|
||||
|
||||
return bitmaps;
|
||||
}
|
||||
|
||||
|
||||
std::unordered_map<wxString, wxBitmap> PLUGIN_CONTENT_MANAGER::GetInstalledPackageBitmaps()
|
||||
{
|
||||
std::unordered_map<wxString, wxBitmap> bitmaps;
|
||||
|
||||
wxFileName resources_dir_fn( m_3rdparty_path, "" );
|
||||
resources_dir_fn.AppendDir( "resources" );
|
||||
wxDir resources_dir( resources_dir_fn.GetPath() );
|
||||
|
||||
if( !resources_dir.IsOpened() )
|
||||
return bitmaps;
|
||||
|
||||
wxString subdir;
|
||||
bool more = resources_dir.GetFirst( &subdir, "", wxDIR_DIRS | wxDIR_HIDDEN );
|
||||
|
||||
while( more )
|
||||
{
|
||||
wxFileName icon( resources_dir_fn.GetPath(), "icon.png" );
|
||||
icon.AppendDir( subdir );
|
||||
|
||||
if( icon.FileExists() )
|
||||
{
|
||||
try
|
||||
{
|
||||
wxBitmap bitmap( icon.GetFullPath(), wxBITMAP_TYPE_PNG );
|
||||
bitmaps.emplace( subdir, bitmap );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
// Log and ignore
|
||||
wxLogTrace( "Error loading png bitmap from %s", icon.GetFullPath() );
|
||||
}
|
||||
}
|
||||
|
||||
more = resources_dir.GetNext( &subdir );
|
||||
}
|
||||
|
||||
return bitmaps;
|
||||
}
|
|
@ -0,0 +1,314 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 Andrew Lutsenko, anlutsenko at gmail dot com
|
||||
* Copyright (C) 1992-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 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 PCM_H_
|
||||
#define PCM_H_
|
||||
|
||||
#include "core/wx_stl_compat.h"
|
||||
#include "pcm_data.h"
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <nlohmann/json-schema.hpp>
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include <wx/wx.h>
|
||||
|
||||
|
||||
///< Contains list of all valid directories that get extracted from a package archive
|
||||
const std::unordered_set<wxString> PCM_PACKAGE_DIRECTORIES( {
|
||||
"plugins",
|
||||
"footprints",
|
||||
"models",
|
||||
"symbols",
|
||||
"resources",
|
||||
} );
|
||||
|
||||
|
||||
///< Package states
|
||||
///< Package is available if it is not installed and there is a compatible version
|
||||
///< Package is unavailable if it is not installed and there are no compatible versions
|
||||
///< Pending states are intermediary when (un)installation is scheduled but not yet performed
|
||||
enum PCM_PACKAGE_STATE
|
||||
{
|
||||
PPS_AVAILABLE = 0,
|
||||
PPS_UNAVAILABLE = 1,
|
||||
PPS_INSTALLED = 2,
|
||||
PPS_PENDING_INSTALL = 3,
|
||||
PPS_PENDING_UNINSTALL = 4
|
||||
};
|
||||
|
||||
|
||||
///< Package actions
|
||||
enum PCM_PACKAGE_ACTION
|
||||
{
|
||||
PPA_INSTALL = 0,
|
||||
PPA_UNINSTALL = 1
|
||||
};
|
||||
|
||||
|
||||
typedef std::vector<std::pair<wxString, wxString>> STRING_PAIR_LIST;
|
||||
typedef std::vector<std::tuple<wxString, wxString, wxString>> STRING_TUPLE_LIST;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Main class of Plugin and Content Manager subsystem
|
||||
*
|
||||
* This class handles logistics of repository management, caching, json validation,
|
||||
* tracking installed packages and provides some utility methods.
|
||||
*
|
||||
* Repository caching is done in $KICADX_3RD_PARTY/cache directory with each
|
||||
* repository storing it's metadata, packages and optionally resource files under
|
||||
* it's id subdirectory.
|
||||
*
|
||||
* Repository id is a prefix of sha256 of it's main url.
|
||||
*
|
||||
* JSON schema file is expected to be in $KICAD_DATA/schemas directory
|
||||
*
|
||||
* Installed packages are stored in <user_settings>/installed_packages.json
|
||||
* If that file is missing PCM will try to reconstruct it from existing
|
||||
* directory structure inside $KICADX_3RD_PARTY but package descriptions
|
||||
* and other metadata will be lost.
|
||||
*/
|
||||
class PLUGIN_CONTENT_MANAGER
|
||||
{
|
||||
public:
|
||||
PLUGIN_CONTENT_MANAGER( wxWindow* aParent );
|
||||
~PLUGIN_CONTENT_MANAGER();
|
||||
|
||||
/**
|
||||
* @brief Fetches repository metadata from given url
|
||||
*
|
||||
* @param url URL of the repository
|
||||
* @param repository fetched repository metadata
|
||||
* @return true if successful
|
||||
* @return false if URL could not be downloaded or result could not be parsed
|
||||
*/
|
||||
bool FetchRepository( const wxString& aUrl, PCM_REPOSITORY& aRepository );
|
||||
|
||||
/**
|
||||
* @brief Validates json against a specific definition in the PCM schema
|
||||
*
|
||||
* @param aJson JSON object to validate
|
||||
* @param aUri JSON URI of a definition to validate against, default is root
|
||||
* @throws std::invalid_argument on validation failure
|
||||
*/
|
||||
void ValidateJson( const nlohmann::json& aJson,
|
||||
const nlohmann::json_uri& aUri = nlohmann::json_uri( "#" ) ) const;
|
||||
|
||||
/**
|
||||
* @brief Verifies SHA256 hash of a binary stream
|
||||
*
|
||||
* @param aStream input stream
|
||||
* @param aHash sha256 lowercase hex string
|
||||
* @return true if hash matches
|
||||
*/
|
||||
bool VerifyHash( std::istream& aStream, const wxString& aHash ) const;
|
||||
|
||||
/**
|
||||
* @brief Set list of repositories
|
||||
*
|
||||
* Discards cache of repositories that were previously cached but are not
|
||||
* on the new list of repositories.
|
||||
*
|
||||
* @param aRepositories list of <URL, name> pairs of repositories
|
||||
*/
|
||||
void SetRepositoryList( const STRING_PAIR_LIST& aRepositories );
|
||||
|
||||
/**
|
||||
* @brief Discard in-memory and on-disk cache of a repository
|
||||
*
|
||||
* @param aRepositoryId id of the repository
|
||||
*/
|
||||
void DiscardRepositoryCache( const wxString& aRepositoryId );
|
||||
|
||||
/**
|
||||
* @brief Mark package as installed
|
||||
*
|
||||
* @param aPackage package metadata
|
||||
* @param aVersion installed package version
|
||||
* @param aRepositoryId id of the source repository or empty estring if
|
||||
* installed from a local file
|
||||
*/
|
||||
void MarkInstalled( const PCM_PACKAGE& aPackage, const wxString& aVersion,
|
||||
const wxString& aRepositoryId );
|
||||
|
||||
/**
|
||||
* @brief Mark package as uninstalled
|
||||
*
|
||||
* @param aPackage package metadata
|
||||
*/
|
||||
void MarkUninstalled( const PCM_PACKAGE& aPackage );
|
||||
|
||||
/**
|
||||
* @brief Get list of repositories
|
||||
*
|
||||
* @return const STRING_TUPLE_LIST& list of repositories in <id, URL, name> tuple format
|
||||
*/
|
||||
const STRING_TUPLE_LIST& GetRepositoryList() const { return m_repository_list; }
|
||||
|
||||
/**
|
||||
* @brief Cache specified repository packages and other metadata
|
||||
*
|
||||
* This method fetches latest repository metadata, checks if there is cache on disk,
|
||||
* compares it's last update timestamp to repository metadata and redownloads packages
|
||||
* list if necessary.
|
||||
* Then it checks sha256 if provided and parses the package list.
|
||||
* Parsed packages metadata is stored in memory.
|
||||
*
|
||||
* Process is repeated with resources file except it is just stored on disk and
|
||||
* any errors at this stage are ignored.
|
||||
*
|
||||
* @param aRepositoryId id of the repository to cache
|
||||
* @return true if packages metadata was cached successfully
|
||||
*/
|
||||
const bool CacheRepository( const wxString& aRepositoryId );
|
||||
|
||||
/**
|
||||
* @brief Get the packages metadata from a previously cached repository
|
||||
*
|
||||
* This should only be called after a successful CacheRepository call
|
||||
*
|
||||
* @param aRepositoryId id of the repository
|
||||
* @return list of package metadata objects
|
||||
*/
|
||||
const std::vector<PCM_PACKAGE>& GetRepositoryPackages( const wxString& aRepositoryId ) const;
|
||||
|
||||
/**
|
||||
* @brief Get list of installed packages
|
||||
*
|
||||
* @return vector of PCM_INSTALLATION_ENTRY objects
|
||||
*/
|
||||
const std::vector<PCM_INSTALLATION_ENTRY> GetInstalledPackages() const;
|
||||
|
||||
/**
|
||||
* @brief Get the current version of an installed package
|
||||
*
|
||||
* @param aPackageId id of the package
|
||||
* @return current version
|
||||
* @throws std::out_of_range if package with given id is not installed
|
||||
*/
|
||||
const wxString& GetInstalledPackageVersion( const wxString& aPackageId ) const;
|
||||
|
||||
///< Returns current 3rd party directory path
|
||||
const wxString& Get3rdPartyPath() const { return m_3rdparty_path; };
|
||||
|
||||
/**
|
||||
* @brief Get current state of the package
|
||||
*
|
||||
* @param aRepositoryId repository id
|
||||
* @param aPackageId package id
|
||||
* @return PCM_PACKAGE_STATE
|
||||
*/
|
||||
PCM_PACKAGE_STATE GetPackageState( const wxString& aRepositoryId, const wxString& aPackageId );
|
||||
|
||||
/**
|
||||
* @brief Downloads url to an output stream
|
||||
*
|
||||
* @param aUrl URL to download
|
||||
* @param aOutput output stream
|
||||
* @param aDialogTitle title of the spawned WX_PROGRESS_REPORTER dialog
|
||||
* @param aSizeLimit maximum download size, 0 for unlimited
|
||||
* @return true if download was successful
|
||||
* @return false if download failed or was too large
|
||||
*/
|
||||
bool DownloadToStream( const wxString& aUrl, std::ostream* aOutput,
|
||||
const wxString& aDialogTitle,
|
||||
const size_t aSizeLimit = DEFAULT_DOWNLOAD_MEM_LIMIT );
|
||||
|
||||
/**
|
||||
* @brief Get the approximate measure of how much given package matches the search term
|
||||
*
|
||||
* @param aPackage package metadata object
|
||||
* @param aSearchTerm search term
|
||||
* @return int search rank, higher number means better match, 0 means no match
|
||||
*/
|
||||
int GetPackageSearchRank( const PCM_PACKAGE& aPackage, const wxString& aSearchTerm );
|
||||
|
||||
/**
|
||||
* @brief Get the icon bitmaps for repository packages
|
||||
*
|
||||
* Repository package icons are taken from repository's resources zip file
|
||||
*
|
||||
* @param aRepositoryId id of the repository
|
||||
* @return map of package id -> bitmap
|
||||
*/
|
||||
std::unordered_map<wxString, wxBitmap>
|
||||
GetRepositoryPackageBitmaps( const wxString& aRepositoryId );
|
||||
|
||||
/**
|
||||
* @brief Get the icon bitmaps for installed packages
|
||||
*
|
||||
* Icons for installed packages are taken from package extracted files in
|
||||
* $KICADX_3RD_PARTY/resources/<packageid> directories
|
||||
*
|
||||
* @return map of package id -> bitmap
|
||||
*/
|
||||
std::unordered_map<wxString, wxBitmap> GetInstalledPackageBitmaps();
|
||||
|
||||
private:
|
||||
///< Default download limit of 10 Mb to not use too much memory
|
||||
static constexpr size_t DEFAULT_DOWNLOAD_MEM_LIMIT = 10 * 1024 * 1024;
|
||||
|
||||
/**
|
||||
* @brief Downloads packages metadata to in memory stream, verifies hash and attempts to parse it
|
||||
*
|
||||
* @param aUrl URL of the packages metadata
|
||||
* @param aHash optional sha256 hash
|
||||
* @param aPackages resulting packages metadata list
|
||||
* @return true if packages were successfully downloaded, verified and parsed
|
||||
*/
|
||||
bool fetchPackages( const wxString& aUrl, const boost::optional<wxString>& aHash,
|
||||
std::vector<PCM_PACKAGE>& aPackages );
|
||||
|
||||
/**
|
||||
* @brief Get the cached repository metadata
|
||||
*
|
||||
* @param aRepositoryId id of the repository
|
||||
* @return const PCM_REPOSITORY&
|
||||
*/
|
||||
const PCM_REPOSITORY& getCachedRepository( const wxString& aRepositoryId ) const;
|
||||
|
||||
/**
|
||||
* @brief Parses version strings and calculates compatibility
|
||||
*
|
||||
* This should be called after loading package metadata from repository or from
|
||||
* installation entries
|
||||
*
|
||||
* @param aPackage package metadata object
|
||||
*/
|
||||
static void preparePackage( PCM_PACKAGE& aPackage );
|
||||
|
||||
///< Returns current UTC timestamp
|
||||
time_t getCurrentTimestamp() const;
|
||||
|
||||
wxWindow* m_dialog;
|
||||
nlohmann::json_schema::json_validator m_schema_validator;
|
||||
wxString m_3rdparty_path;
|
||||
wxString m_cache_path;
|
||||
std::unordered_map<wxString, PCM_REPOSITORY> m_repository_cache;
|
||||
STRING_TUPLE_LIST m_repository_list; // (id, name, url) tuples
|
||||
// Using sorted map to keep order of entries in installed list stable
|
||||
std::map<wxString, PCM_INSTALLATION_ENTRY> m_installed;
|
||||
const static std::tuple<int, int> m_kicad_version;
|
||||
};
|
||||
|
||||
#endif // PCM_H_
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 Andrew Lutsenko, anlutsenko at gmail dot com
|
||||
* Copyright (C) 1992-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 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 "pcm_data.h"
|
||||
|
||||
|
||||
template <typename T>
|
||||
void to_optional( const json& j, const char* key, boost::optional<T>& dest )
|
||||
{
|
||||
if( j.contains( key ) )
|
||||
{
|
||||
T tmp;
|
||||
j.at( key ).get_to( tmp );
|
||||
dest.emplace( tmp );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void to_json( json& j, const PACKAGE_VERSION& v )
|
||||
{
|
||||
j = json{ { "version", v.version },
|
||||
{ "status", v.status },
|
||||
{ "kicad_version", v.kicad_version } };
|
||||
|
||||
if( v.version_epoch )
|
||||
j["version_epoch"] = v.version_epoch.get();
|
||||
|
||||
if( v.download_url )
|
||||
j["download_url"] = v.download_url.get();
|
||||
|
||||
if( v.download_sha256 )
|
||||
j["download_sha256"] = v.download_sha256.get();
|
||||
|
||||
if( v.download_size )
|
||||
j["download_size"] = v.download_size.get();
|
||||
|
||||
if( v.install_size )
|
||||
j["install_size"] = v.install_size.get();
|
||||
|
||||
if( v.platforms.size() > 0 )
|
||||
nlohmann::to_json( j["platforms"], v.platforms );
|
||||
|
||||
if( v.kicad_version_max )
|
||||
j["kicad_version_max"] = v.kicad_version_max.get();
|
||||
}
|
||||
|
||||
|
||||
void from_json( const json& j, PACKAGE_VERSION& v )
|
||||
{
|
||||
j.at( "version" ).get_to( v.version );
|
||||
j.at( "status" ).get_to( v.status );
|
||||
j.at( "kicad_version" ).get_to( v.kicad_version );
|
||||
|
||||
to_optional( j, "version_epoch", v.version_epoch );
|
||||
to_optional( j, "download_url", v.download_url );
|
||||
to_optional( j, "download_sha256", v.download_sha256 );
|
||||
to_optional( j, "download_size", v.download_size );
|
||||
to_optional( j, "install_size", v.install_size );
|
||||
to_optional( j, "kicad_version_max", v.kicad_version_max );
|
||||
|
||||
if( j.contains( "platforms" ) )
|
||||
j.at( "platforms" ).get_to( v.platforms );
|
||||
}
|
||||
|
||||
|
||||
void to_json( json& j, const PCM_PACKAGE& p )
|
||||
{
|
||||
j = json{ { "name", p.name },
|
||||
{ "description", p.description },
|
||||
{ "description_full", p.description_full },
|
||||
{ "identifier", p.identifier },
|
||||
{ "type", p.type },
|
||||
{ "author", p.author },
|
||||
{ "license", p.license },
|
||||
{ "resources", p.resources },
|
||||
{ "versions", p.versions } };
|
||||
|
||||
if( p.maintainer )
|
||||
j["maintainer"] = p.maintainer.get();
|
||||
|
||||
if( p.tags.size() > 0 )
|
||||
j["tags"] = p.tags;
|
||||
}
|
||||
|
||||
|
||||
void from_json( const json& j, PCM_PACKAGE& p )
|
||||
{
|
||||
j.at( "name" ).get_to( p.name );
|
||||
j.at( "description" ).get_to( p.description );
|
||||
j.at( "description_full" ).get_to( p.description_full );
|
||||
j.at( "identifier" ).get_to( p.identifier );
|
||||
j.at( "type" ).get_to( p.type );
|
||||
j.at( "author" ).get_to( p.author );
|
||||
j.at( "license" ).get_to( p.license );
|
||||
j.at( "resources" ).get_to( p.resources );
|
||||
j.at( "versions" ).get_to( p.versions );
|
||||
|
||||
to_optional( j, "maintainer", p.maintainer );
|
||||
|
||||
if( j.contains( "tags" ) )
|
||||
j.at( "tags" ).get_to( p.tags );
|
||||
}
|
||||
|
||||
|
||||
void to_json( json& j, const PCM_RESOURCE_REFERENCE& r )
|
||||
{
|
||||
j = json{ { "url", r.url }, { "update_timestamp", r.update_timestamp } };
|
||||
|
||||
if( r.sha256 )
|
||||
j["sha256"] = r.sha256.get();
|
||||
}
|
||||
|
||||
|
||||
void from_json( const json& j, PCM_RESOURCE_REFERENCE& r )
|
||||
{
|
||||
j.at( "url" ).get_to( r.url );
|
||||
j.at( "update_timestamp" ).get_to( r.update_timestamp );
|
||||
|
||||
to_optional(j, "sha256", r.sha256 );
|
||||
}
|
||||
|
||||
|
||||
void to_json( json& j, const PCM_REPOSITORY& r )
|
||||
{
|
||||
j = json{ { "name", r.name }, { "packages", r.packages } };
|
||||
|
||||
if( r.resources )
|
||||
j["resources"] = r.resources.get();
|
||||
|
||||
if( r.manifests )
|
||||
j["manifests"] = r.manifests.get();
|
||||
|
||||
if( r.maintainer )
|
||||
j["maintainer"] = r.maintainer.get();
|
||||
}
|
||||
|
||||
|
||||
void from_json( const json& j, PCM_REPOSITORY& r )
|
||||
{
|
||||
j.at( "name" ).get_to( r.name );
|
||||
j.at( "packages" ).get_to( r.packages );
|
||||
|
||||
to_optional(j, "resources", r.resources );
|
||||
to_optional(j, "manifests", r.manifests );
|
||||
to_optional(j, "maintainer", r.maintainer );
|
||||
}
|
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 Andrew Lutsenko, anlutsenko at gmail dot com
|
||||
* Copyright (C) 1992-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 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 PCM_DATA_H_
|
||||
#define PCM_DATA_H_
|
||||
|
||||
#include "core/wx_stl_compat.h"
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <map>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <wx/string.h>
|
||||
|
||||
|
||||
using STRING_MAP = std::map<std::string, wxString>;
|
||||
using nlohmann::json;
|
||||
|
||||
|
||||
///< Supported package types
|
||||
enum PCM_PACKAGE_TYPE
|
||||
{
|
||||
PT_INVALID,
|
||||
PT_PLUGIN,
|
||||
PT_LIBRARY,
|
||||
};
|
||||
|
||||
|
||||
///< Status of specific package version
|
||||
enum PCM_PACKAGE_VERSION_STATUS
|
||||
{
|
||||
PVS_INVALID,
|
||||
PVS_STABLE,
|
||||
PVS_TESTING,
|
||||
PVS_DEVELOPMENT,
|
||||
PVS_DEPRECATED
|
||||
};
|
||||
|
||||
|
||||
///< Describes a person's name and contact information
|
||||
struct PCM_CONTACT
|
||||
{
|
||||
wxString name;
|
||||
STRING_MAP contact;
|
||||
};
|
||||
|
||||
|
||||
// MSVC, wxWidgets and nlohmann_json don't play nice together and
|
||||
// create linker errors about redefinition of some vector members
|
||||
// if an attempt to use vector<wxString> in json is made.
|
||||
|
||||
///< Package version metadata
|
||||
struct PACKAGE_VERSION
|
||||
{
|
||||
wxString version;
|
||||
boost::optional<int> version_epoch;
|
||||
boost::optional<wxString> download_url;
|
||||
boost::optional<wxString> download_sha256;
|
||||
boost::optional<uint64_t> download_size;
|
||||
boost::optional<uint64_t> install_size;
|
||||
PCM_PACKAGE_VERSION_STATUS status;
|
||||
std::vector<std::string> platforms;
|
||||
wxString kicad_version;
|
||||
boost::optional<wxString> kicad_version_max;
|
||||
|
||||
// Not serialized fields
|
||||
std::tuple<int, int, int, int> parsed_version; // Full version tuple for sorting
|
||||
bool compatible;
|
||||
};
|
||||
|
||||
|
||||
///< Package metadata
|
||||
struct PCM_PACKAGE
|
||||
{
|
||||
wxString name;
|
||||
wxString description;
|
||||
wxString description_full;
|
||||
wxString identifier;
|
||||
PCM_PACKAGE_TYPE type;
|
||||
PCM_CONTACT author;
|
||||
boost::optional<PCM_CONTACT> maintainer;
|
||||
wxString license;
|
||||
STRING_MAP resources;
|
||||
std::vector<std::string> tags;
|
||||
std::vector<PACKAGE_VERSION> versions;
|
||||
};
|
||||
|
||||
|
||||
///< Repository reference to a resource
|
||||
struct PCM_RESOURCE_REFERENCE
|
||||
{
|
||||
wxString url;
|
||||
boost::optional<wxString> sha256;
|
||||
uint64_t update_timestamp;
|
||||
};
|
||||
|
||||
|
||||
///< Repository metadata
|
||||
struct PCM_REPOSITORY
|
||||
{
|
||||
wxString name;
|
||||
PCM_RESOURCE_REFERENCE packages;
|
||||
boost::optional<PCM_RESOURCE_REFERENCE> resources;
|
||||
boost::optional<PCM_RESOURCE_REFERENCE> manifests;
|
||||
boost::optional<PCM_CONTACT> maintainer;
|
||||
|
||||
// Not serialized fields
|
||||
std::vector<PCM_PACKAGE> package_list;
|
||||
};
|
||||
|
||||
|
||||
///< Package installation entry
|
||||
struct PCM_INSTALLATION_ENTRY
|
||||
{
|
||||
PCM_PACKAGE package;
|
||||
wxString current_version;
|
||||
wxString repository_id;
|
||||
wxString repository_name;
|
||||
uint64_t install_timestamp;
|
||||
};
|
||||
|
||||
|
||||
// Teaching json en/decoder to understand wxStrings
|
||||
namespace nlohmann
|
||||
{
|
||||
template <>
|
||||
struct adl_serializer<wxString>
|
||||
{
|
||||
static void to_json( json& j, const wxString& s ) { j = s.ToUTF8(); }
|
||||
|
||||
static void from_json( const json& j, wxString& s )
|
||||
{
|
||||
s = wxString::FromUTF8( j.get<std::string>().c_str() );
|
||||
}
|
||||
};
|
||||
} // namespace nlohmann
|
||||
|
||||
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM( PCM_PACKAGE_TYPE, {
|
||||
{ PT_INVALID, "invalid" },
|
||||
{ PT_PLUGIN, "plugin" },
|
||||
{ PT_LIBRARY, "library" },
|
||||
} )
|
||||
|
||||
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM( PCM_PACKAGE_VERSION_STATUS,
|
||||
{
|
||||
{ PVS_INVALID, "invalid" },
|
||||
{ PVS_STABLE, "stable" },
|
||||
{ PVS_TESTING, "testing" },
|
||||
{ PVS_DEVELOPMENT, "development" },
|
||||
{ PVS_DEPRECATED, "deprecated" },
|
||||
} )
|
||||
|
||||
|
||||
// Following are templates and definitions for en/decoding above structs
|
||||
// to/from json
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE( PCM_CONTACT, name, contact )
|
||||
|
||||
|
||||
void to_json( json& j, const PACKAGE_VERSION& v );
|
||||
void from_json( const json& j, PACKAGE_VERSION& v );
|
||||
|
||||
|
||||
void to_json( json& j, const PCM_PACKAGE& p );
|
||||
void from_json( const json& j, PCM_PACKAGE& p );
|
||||
|
||||
|
||||
void to_json( json& j, const PCM_RESOURCE_REFERENCE& r );
|
||||
void from_json( const json& j, PCM_RESOURCE_REFERENCE& r );
|
||||
|
||||
|
||||
void to_json( json& j, const PCM_REPOSITORY& r );
|
||||
void from_json( const json& j, PCM_REPOSITORY& r );
|
||||
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE( PCM_INSTALLATION_ENTRY, package, current_version, repository_id,
|
||||
repository_name, install_timestamp );
|
||||
|
||||
|
||||
#endif // PCM_DATA_H_
|
|
@ -0,0 +1,455 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 Andrew Lutsenko, anlutsenko at gmail dot com
|
||||
* Copyright (C) 1992-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 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 "pcm_task_manager.h"
|
||||
#include "kicad_curl/kicad_curl_easy.h"
|
||||
#include "paths.h"
|
||||
#include "picosha2.h"
|
||||
#include "reporter.h"
|
||||
#include "wxstream_helper.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
#include <unordered_set>
|
||||
#include <wx/dir.h>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/fs_zip.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/sstream.h>
|
||||
#include <wx/wfstream.h>
|
||||
#include <wx/zipstrm.h>
|
||||
|
||||
|
||||
void PCM_TASK_MANAGER::DownloadAndInstall( const PCM_PACKAGE& aPackage, const wxString& aVersion,
|
||||
const wxString& aRepositoryId )
|
||||
{
|
||||
PCM_TASK download_task = [aPackage, aVersion, aRepositoryId, this]()
|
||||
{
|
||||
wxFileName file_path( m_pcm->Get3rdPartyPath(), "" );
|
||||
file_path.AppendDir( "cache" );
|
||||
file_path.SetFullName( wxString::Format( "%s_v%s.zip", aPackage.identifier, aVersion ) );
|
||||
|
||||
auto pkgver = std::find_if( aPackage.versions.begin(), aPackage.versions.end(),
|
||||
[&aVersion]( const PACKAGE_VERSION& pv )
|
||||
{
|
||||
return pv.version == aVersion;
|
||||
} );
|
||||
|
||||
wxASSERT_MSG( pkgver != aPackage.versions.end(), "Package version not found" );
|
||||
|
||||
if( !wxDirExists( file_path.GetPath() )
|
||||
&& !wxFileName::Mkdir( file_path.GetPath(), wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
|
||||
{
|
||||
m_reporter->Report( _( "Unable to create download directory!" ), RPT_SEVERITY_ERROR );
|
||||
return;
|
||||
}
|
||||
|
||||
int code = downloadFile( file_path.GetFullPath(), pkgver->download_url.get() );
|
||||
|
||||
if( code == CURLE_OK )
|
||||
{
|
||||
PCM_TASK install_task = [aPackage, aVersion, aRepositoryId, file_path, this]()
|
||||
{
|
||||
auto pkgver = std::find_if( aPackage.versions.begin(), aPackage.versions.end(),
|
||||
[&aVersion]( const PACKAGE_VERSION& pv )
|
||||
{
|
||||
return pv.version == aVersion;
|
||||
} );
|
||||
|
||||
const boost::optional<wxString>& hash = pkgver->download_sha256;
|
||||
bool hash_match = true;
|
||||
|
||||
if( hash )
|
||||
{
|
||||
std::ifstream stream( file_path.GetFullPath().ToUTF8(), std::ios::binary );
|
||||
hash_match = m_pcm->VerifyHash( stream, hash.get() );
|
||||
}
|
||||
|
||||
if( !hash_match )
|
||||
{
|
||||
m_reporter->Report(
|
||||
wxString::Format(
|
||||
_( "Downloaded archive hash for package %s does not match "
|
||||
"repository entry. This may indicate a problem with the "
|
||||
"package, if the issue persists report this to repository "
|
||||
"maintainers." ),
|
||||
aPackage.identifier ),
|
||||
RPT_SEVERITY_ERROR );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_reporter->Report( wxString::Format( _( "Extracting package %s. " ),
|
||||
aPackage.identifier ) );
|
||||
|
||||
if( extract( file_path.GetFullPath(), aPackage.identifier ) )
|
||||
{
|
||||
m_pcm->MarkInstalled( aPackage, pkgver->version, aRepositoryId );
|
||||
// TODO register libraries.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cleanup possibly partially extracted package
|
||||
deletePackageDirectories( aPackage.identifier );
|
||||
}
|
||||
}
|
||||
|
||||
m_reporter->Report( wxString::Format( _( "Removing downloaded archive %s. " ),
|
||||
file_path.GetFullName() ) );
|
||||
wxRemoveFile( file_path.GetFullPath() );
|
||||
};
|
||||
|
||||
m_install_queue.push( install_task );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cleanup after ourselves.
|
||||
wxRemoveFile( file_path.GetFullPath() );
|
||||
}
|
||||
};
|
||||
|
||||
m_download_queue.push( download_task );
|
||||
}
|
||||
|
||||
|
||||
int PCM_TASK_MANAGER::downloadFile( const wxString& aFilePath, const wxString& url )
|
||||
{
|
||||
TRANSFER_CALLBACK callback = [&]( size_t dltotal, size_t dlnow, size_t ultotal, size_t ulnow )
|
||||
{
|
||||
if( dltotal > 1024 )
|
||||
{
|
||||
m_reporter->SetDownloadProgress( dlnow, dltotal );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_reporter->SetDownloadProgress( 0.0, 0.0 );
|
||||
}
|
||||
return m_reporter->IsCancelled();
|
||||
};
|
||||
|
||||
std::ofstream out( aFilePath.ToUTF8(), std::ofstream::binary );
|
||||
|
||||
KICAD_CURL_EASY curl;
|
||||
curl.SetOutputStream( &out );
|
||||
curl.SetURL( url.ToUTF8().data() );
|
||||
curl.SetFollowRedirects( true );
|
||||
curl.SetTransferCallback( callback, 250000L );
|
||||
|
||||
m_reporter->Report( wxString::Format( _( "Downloading package url: %s" ), url ) );
|
||||
|
||||
int code = curl.Perform();
|
||||
|
||||
out.close();
|
||||
|
||||
uint64_t download_total;
|
||||
|
||||
if( CURLE_OK == curl.GetTransferTotal( download_total ) )
|
||||
m_reporter->SetDownloadProgress( download_total, download_total );
|
||||
|
||||
if( code != CURLE_OK && code != CURLE_ABORTED_BY_CALLBACK )
|
||||
{
|
||||
m_reporter->Report( wxString::Format( _( "Failed to download url %s\n%s" ), url,
|
||||
curl.GetErrorText( code ) ),
|
||||
RPT_SEVERITY_ERROR );
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
bool PCM_TASK_MANAGER::extract( const wxString& aFilePath, const wxString& aPackageId )
|
||||
{
|
||||
wxFFileInputStream stream( aFilePath );
|
||||
wxZipInputStream zip( stream );
|
||||
|
||||
wxLogNull no_wx_logging;
|
||||
|
||||
int entries = zip.GetTotalEntries();
|
||||
int extracted = 0;
|
||||
|
||||
wxArchiveEntry* entry = zip.GetNextEntry();
|
||||
|
||||
if( !zip.IsOk() )
|
||||
{
|
||||
m_reporter->Report( _( "Error extracting file!" ), RPT_SEVERITY_ERROR );
|
||||
return false;
|
||||
}
|
||||
|
||||
for( ; entry; entry = zip.GetNextEntry() )
|
||||
{
|
||||
wxArrayString path_parts =
|
||||
wxSplit( entry->GetName(), wxFileName::GetPathSeparator(), (wxChar) NULL );
|
||||
|
||||
if( path_parts.size() < 2
|
||||
|| PCM_PACKAGE_DIRECTORIES.find( path_parts[0] ) == PCM_PACKAGE_DIRECTORIES.end()
|
||||
|| path_parts[path_parts.size() - 1].IsEmpty() )
|
||||
{
|
||||
// Ignore files in the root of the archive and files outside of package dirs.
|
||||
continue;
|
||||
}
|
||||
|
||||
// m_reporter->Report( wxString::Format( _( "Extracting file \"%s\"\n" ), entry->GetName() ),
|
||||
// RPT_SEVERITY_INFO );
|
||||
|
||||
// Transform paths from
|
||||
// <PackageRoot>/$folder/$contents
|
||||
// To
|
||||
// $KICAD6_3RD_PARTY/$folder/$package_id/$contents
|
||||
path_parts.Insert( aPackageId, 1 );
|
||||
path_parts.Insert( m_pcm->Get3rdPartyPath(), 0 );
|
||||
|
||||
wxString fullname = wxJoin( path_parts, wxFileName::GetPathSeparator(), (wxChar) NULL );
|
||||
|
||||
// Ensure the target directory exists and create it if not.
|
||||
wxString t_path = wxPathOnly( fullname );
|
||||
|
||||
if( !wxDirExists( t_path ) )
|
||||
{
|
||||
wxFileName::Mkdir( t_path, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
|
||||
}
|
||||
|
||||
wxTempFileOutputStream out( fullname );
|
||||
|
||||
if( !( CopyStreamData( zip, out, entry->GetSize() ) && out.Commit() ) )
|
||||
{
|
||||
m_reporter->Report( _( "Error extracting file!" ), RPT_SEVERITY_ERROR );
|
||||
return false;
|
||||
}
|
||||
|
||||
extracted++;
|
||||
m_reporter->SetOverallProgress( extracted, entries );
|
||||
|
||||
if( m_reporter->IsCancelled() )
|
||||
break;
|
||||
}
|
||||
|
||||
zip.CloseEntry();
|
||||
|
||||
if( m_reporter->IsCancelled() )
|
||||
{
|
||||
m_reporter->Report( _( "Aborting package installation." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
m_reporter->Report( wxT( "Extracted package\n" ), RPT_SEVERITY_INFO );
|
||||
m_reporter->SetOverallProgress( entries, entries );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void PCM_TASK_MANAGER::InstallFromFile( wxWindow* aParent, const wxString& aFilePath )
|
||||
{
|
||||
wxFFileInputStream stream( aFilePath );
|
||||
|
||||
if( !stream.IsOk() )
|
||||
{
|
||||
wxLogError( _( "Could not open archive file." ) );
|
||||
return;
|
||||
}
|
||||
|
||||
wxZipInputStream zip( stream );
|
||||
|
||||
if( !zip.IsOk() )
|
||||
{
|
||||
wxLogError( _( "Invalid archive file format." ) );
|
||||
return;
|
||||
}
|
||||
|
||||
nlohmann::json metadata;
|
||||
|
||||
for( wxArchiveEntry* entry = zip.GetNextEntry(); entry != nullptr; entry = zip.GetNextEntry() )
|
||||
{
|
||||
// Find and load metadata.json
|
||||
if( entry->GetName() != "metadata.json" )
|
||||
continue;
|
||||
|
||||
wxStringOutputStream strStream;
|
||||
|
||||
if( CopyStreamData( zip, strStream, entry->GetSize() ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
metadata = nlohmann::json::parse( strStream.GetString().ToUTF8().data() );
|
||||
m_pcm->ValidateJson( metadata );
|
||||
}
|
||||
catch( const std::exception& e )
|
||||
{
|
||||
wxLogError( wxString::Format( _( "Unable to parse package metadata:\n\n%s" ),
|
||||
e.what() ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( metadata.empty() )
|
||||
{
|
||||
wxLogError( _( "Archive does not contain a valid metadata.json file" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
PCM_PACKAGE package = metadata.get<PCM_PACKAGE>();
|
||||
|
||||
if( package.versions.size() != 1 )
|
||||
{
|
||||
wxLogError( _( "Archive metadata must have a single version defined" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
const auto installed_packages = m_pcm->GetInstalledPackages();
|
||||
if( std::find_if( installed_packages.begin(), installed_packages.end(),
|
||||
[&]( const PCM_INSTALLATION_ENTRY& entry )
|
||||
{
|
||||
return entry.package.identifier == package.identifier;
|
||||
} )
|
||||
!= installed_packages.end() )
|
||||
{
|
||||
wxLogError( wxString::Format( _( "Package with identifier %s is already installed, you "
|
||||
"must first uninstall this package." ),
|
||||
package.identifier ) );
|
||||
return;
|
||||
}
|
||||
|
||||
m_reporter = new DIALOG_PCM_PROGRESS( aParent, false );
|
||||
m_reporter->Show();
|
||||
|
||||
if( extract( aFilePath, package.identifier ) )
|
||||
m_pcm->MarkInstalled( package, package.versions[0].version, "" );
|
||||
|
||||
m_reporter->SetFinished();
|
||||
m_reporter->ShowModal();
|
||||
m_reporter->Destroy();
|
||||
}
|
||||
|
||||
|
||||
void PCM_TASK_MANAGER::deletePackageDirectories( const wxString& aPackageId )
|
||||
{
|
||||
for( const wxString& dir : PCM_PACKAGE_DIRECTORIES )
|
||||
{
|
||||
wxFileName d( m_pcm->Get3rdPartyPath(), "" );
|
||||
d.AppendDir( dir );
|
||||
d.AppendDir( aPackageId );
|
||||
|
||||
if( d.DirExists() )
|
||||
{
|
||||
m_reporter->Report( wxString::Format( _( "Removing directory %s" ), d.GetPath() ) );
|
||||
|
||||
if( !d.Rmdir( wxPATH_RMDIR_RECURSIVE ) )
|
||||
{
|
||||
m_reporter->Report(
|
||||
wxString::Format( _( "Failed to remove directory %s" ), d.GetPath() ),
|
||||
RPT_SEVERITY_ERROR );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PCM_TASK_MANAGER::Uninstall( const PCM_PACKAGE& aPackage )
|
||||
{
|
||||
PCM_TASK task = [aPackage, this]
|
||||
{
|
||||
deletePackageDirectories( aPackage.identifier );
|
||||
|
||||
m_pcm->MarkUninstalled( aPackage );
|
||||
|
||||
m_reporter->Report(
|
||||
wxString::Format( _( "Package %s uninstalled" ), aPackage.identifier ) );
|
||||
};
|
||||
|
||||
m_install_queue.push( task );
|
||||
}
|
||||
|
||||
|
||||
void PCM_TASK_MANAGER::RunQueue( wxWindow* aParent )
|
||||
{
|
||||
m_reporter = new DIALOG_PCM_PROGRESS( aParent );
|
||||
|
||||
m_reporter->SetOverallProgressPhases( m_download_queue.size() + m_install_queue.size() );
|
||||
m_reporter->Show();
|
||||
|
||||
std::mutex mutex;
|
||||
std::condition_variable condvar;
|
||||
bool download_complete = false;
|
||||
|
||||
std::thread download_thread(
|
||||
[&]()
|
||||
{
|
||||
while( !m_download_queue.empty() && !m_reporter->IsCancelled() )
|
||||
{
|
||||
PCM_TASK task;
|
||||
m_download_queue.pop( task );
|
||||
task();
|
||||
condvar.notify_all();
|
||||
}
|
||||
|
||||
m_reporter->SetDownloadsFinished();
|
||||
|
||||
std::unique_lock<std::mutex> lock( mutex );
|
||||
download_complete = true;
|
||||
condvar.notify_all();
|
||||
} );
|
||||
|
||||
std::thread install_thread(
|
||||
[&]()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock( mutex );
|
||||
|
||||
do
|
||||
{
|
||||
condvar.wait( lock,
|
||||
[&]()
|
||||
{
|
||||
return download_complete || !m_install_queue.empty()
|
||||
|| m_reporter->IsCancelled();
|
||||
} );
|
||||
|
||||
lock.unlock();
|
||||
|
||||
while( !m_install_queue.empty() && !m_reporter->IsCancelled() )
|
||||
{
|
||||
PCM_TASK task;
|
||||
m_install_queue.pop( task );
|
||||
task();
|
||||
m_reporter->AdvanceOverallProgressPhase();
|
||||
}
|
||||
|
||||
lock.lock();
|
||||
|
||||
} while( ( !m_install_queue.empty() || !download_complete )
|
||||
&& !m_reporter->IsCancelled() );
|
||||
|
||||
if( m_reporter->IsCancelled() )
|
||||
{
|
||||
m_reporter->SetOverallProgressPhases( 1 );
|
||||
m_reporter->SetOverallProgress( 1, 1 );
|
||||
m_reporter->Report( _( "Aborting remaining tasks." ) );
|
||||
}
|
||||
|
||||
m_reporter->Report( _( "Done." ) );
|
||||
|
||||
m_reporter->SetFinished();
|
||||
} );
|
||||
|
||||
m_reporter->ShowModal();
|
||||
m_reporter->Destroy();
|
||||
|
||||
download_thread.join();
|
||||
install_thread.join();
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 Andrew Lutsenko, anlutsenko at gmail dot com
|
||||
* Copyright (C) 1992-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 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 PCM_TASK_MANAGER_H_
|
||||
#define PCM_TASK_MANAGER_H_
|
||||
|
||||
#include "dialogs/dialog_pcm_progress.h"
|
||||
#include "pcm.h"
|
||||
#include "pcm_data.h"
|
||||
#include "sync_queue.h"
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <nlohmann/json-schema.hpp>
|
||||
#include <widgets/wx_progress_reporters.h>
|
||||
#include <wx/string.h>
|
||||
|
||||
|
||||
typedef std::function<void()> PCM_TASK;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Helper class that handles package (un)installation
|
||||
*
|
||||
* Package state changes are first enqueued using DownloadAndInstall/Uninstall methods
|
||||
* and then applied using RunQueue().
|
||||
*
|
||||
* RunQueue() is multithreaded for better experience.
|
||||
*/
|
||||
class PCM_TASK_MANAGER
|
||||
{
|
||||
public:
|
||||
PCM_TASK_MANAGER( std::shared_ptr<PLUGIN_CONTENT_MANAGER> pcm ) : m_pcm( pcm ){};
|
||||
|
||||
/**
|
||||
* @brief Enqueue package download and installation
|
||||
*
|
||||
* Enqueues a download task for a given package version.
|
||||
*
|
||||
* Download task fetches the package archive and if successful enqueues an installation task.
|
||||
* Installation task verifies sha256 hash if specified, extracts the package, removes the
|
||||
* downloaded archive and marks package as installed.
|
||||
*
|
||||
* Both tasks report their state independently to a progress dialog.
|
||||
*
|
||||
* @param aPackage package metadata
|
||||
* @param aVersion version to be installed
|
||||
* @param aRepositoryId id of the source repository
|
||||
*/
|
||||
void DownloadAndInstall( const PCM_PACKAGE& aPackage, const wxString& aVersion,
|
||||
const wxString& aRepositoryId );
|
||||
|
||||
/**
|
||||
* @brief Enqueue package uninstallation
|
||||
*
|
||||
* Enqueues uninstallation task that removes all package files and marks package
|
||||
* as uninstalled.
|
||||
*
|
||||
* @param aPackage package metadata
|
||||
*/
|
||||
void Uninstall( const PCM_PACKAGE& aPackage );
|
||||
|
||||
/**
|
||||
* @brief Run queue of pending actions
|
||||
*
|
||||
* This method spawns 2 threads to concurrently run tasks in download and install
|
||||
* queues until they are drained.
|
||||
*
|
||||
* Download queue feeds into install queue so the install thread keeps running until
|
||||
* download thread indicated that it's finished AND all installs are processed.
|
||||
*
|
||||
* @param aParent parent dialog for progress window
|
||||
*/
|
||||
void RunQueue( wxWindow* aParent );
|
||||
|
||||
/**
|
||||
* @brief Installs package from an archive file on disk
|
||||
*
|
||||
* Unlike DownloadAndInstall/Uninstall methods this one immediately extracts the package
|
||||
* and marks it as installed.
|
||||
*
|
||||
* @param aParent parent dialog for progress window
|
||||
* @param aFilePath path to the archive file
|
||||
*/
|
||||
void InstallFromFile( wxWindow* aParent, const wxString& aFilePath );
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Download URL to a file
|
||||
*
|
||||
* @param aFilePath path to file
|
||||
* @param aUrl URL to download
|
||||
* @return int CURLE error code
|
||||
*/
|
||||
int downloadFile( const wxString& aFilePath, const wxString& aUrl );
|
||||
|
||||
/**
|
||||
* @brief Extract package archive
|
||||
*
|
||||
* @param aFilePath path to the archive
|
||||
* @param aPackageId id of the package
|
||||
* @return true if archive was extracted successfuly
|
||||
*/
|
||||
bool extract( const wxString& aFilePath, const wxString& aPackageId );
|
||||
|
||||
/**
|
||||
* @brief Delete all package files
|
||||
*
|
||||
* @param aPackageId id of the package
|
||||
*/
|
||||
void deletePackageDirectories( const wxString& aPackageId );
|
||||
|
||||
DIALOG_PCM_PROGRESS* m_reporter;
|
||||
SYNC_QUEUE<PCM_TASK> m_download_queue;
|
||||
SYNC_QUEUE<PCM_TASK> m_install_queue;
|
||||
std::shared_ptr<PLUGIN_CONTENT_MANAGER> m_pcm;
|
||||
};
|
||||
|
||||
|
||||
#endif // PCM_TASK_MANAGER_H_
|
|
@ -111,6 +111,14 @@ TOOL_ACTION KICAD_MANAGER_ACTIONS::editDrawingSheet( "kicad.Control.editDrawingS
|
|||
_( "Drawing Sheet Editor" ), _( "Edit drawing sheet borders and title block" ),
|
||||
BITMAPS::icon_pagelayout_editor_24 );
|
||||
|
||||
#ifdef PCM
|
||||
TOOL_ACTION KICAD_MANAGER_ACTIONS::showPluginManager( "kicad.Control.pluginContentManager",
|
||||
AS_GLOBAL,
|
||||
MD_CTRL + 'M', "",
|
||||
_( "Plugin and Content Manager" ), _( "Run Plugin and Content Manager" ),
|
||||
BITMAPS::icon_pcm_24 );
|
||||
#endif
|
||||
|
||||
TOOL_ACTION KICAD_MANAGER_ACTIONS::openTextEditor( "kicad.Control.openTextEditor",
|
||||
AS_GLOBAL,
|
||||
0, "",
|
||||
|
|
|
@ -46,6 +46,9 @@ public:
|
|||
static TOOL_ACTION showCalculator;
|
||||
static TOOL_ACTION editDrawingSheet;
|
||||
static TOOL_ACTION openTextEditor;
|
||||
#ifdef PCM
|
||||
static TOOL_ACTION showPluginManager;
|
||||
#endif
|
||||
|
||||
static TOOL_ACTION editOtherSch;
|
||||
static TOOL_ACTION editOtherPCB;
|
||||
|
|
|
@ -34,8 +34,12 @@
|
|||
#include <wx/checkbox.h>
|
||||
#include <wx/dir.h>
|
||||
#include <wx/filedlg.h>
|
||||
#ifdef PCM
|
||||
#include "dialog_pcm.h"
|
||||
#endif
|
||||
|
||||
///< Helper widget to select whether a new directory should be created for a project.
|
||||
|
||||
///> Helper widget to select whether a new directory should be created for a project.
|
||||
class DIR_CHECKBOX : public wxPanel
|
||||
{
|
||||
public:
|
||||
|
@ -752,6 +756,14 @@ int KICAD_MANAGER_CONTROL::Execute( const TOOL_EVENT& aEvent )
|
|||
execFile = EESCHEMA_EXE;
|
||||
else if( aEvent.IsAction( &KICAD_MANAGER_ACTIONS::editOtherPCB ) )
|
||||
execFile = PCBNEW_EXE;
|
||||
#ifdef PCM
|
||||
else if( aEvent.IsAction( &KICAD_MANAGER_ACTIONS::showPluginManager ) )
|
||||
{
|
||||
DIALOG_PCM* pcm = new DIALOG_PCM( m_frame );
|
||||
pcm->ShowModal();
|
||||
pcm->Destroy();
|
||||
}
|
||||
#endif
|
||||
else
|
||||
wxFAIL_MSG( "Execute(): unexpected request" );
|
||||
|
||||
|
@ -814,4 +826,8 @@ void KICAD_MANAGER_CONTROL::setTransitions()
|
|||
|
||||
Go( &KICAD_MANAGER_CONTROL::Execute, KICAD_MANAGER_ACTIONS::editOtherSch.MakeEvent() );
|
||||
Go( &KICAD_MANAGER_CONTROL::Execute, KICAD_MANAGER_ACTIONS::editOtherPCB.MakeEvent() );
|
||||
|
||||
#ifdef PCM
|
||||
Go( &KICAD_MANAGER_CONTROL::Execute, KICAD_MANAGER_ACTIONS::showPluginManager.MakeEvent() );
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -104,18 +104,18 @@ void SCRIPTING_TOOL::callLoadPlugins()
|
|||
// Load pcbnew inside Python and load all the user plugins and package-based plugins
|
||||
using namespace pybind11::literals;
|
||||
|
||||
auto locals = pybind11::dict( "sys_path"_a = TO_UTF8( SCRIPTING::PyScriptingPath(
|
||||
SCRIPTING::PATH_TYPE::STOCK ) ),
|
||||
"user_path"_a = TO_UTF8( SCRIPTING::PyScriptingPath(
|
||||
SCRIPTING::PATH_TYPE::USER ) ),
|
||||
"third_party_path"_a = TO_UTF8( SCRIPTING::PyPluginsPath(
|
||||
SCRIPTING::PATH_TYPE::THIRDPARTY ) ) );
|
||||
auto locals = pybind11::dict(
|
||||
"sys_path"_a = TO_UTF8( SCRIPTING::PyScriptingPath( SCRIPTING::PATH_TYPE::STOCK ) ),
|
||||
"user_path"_a = TO_UTF8( SCRIPTING::PyScriptingPath( SCRIPTING::PATH_TYPE::USER ) ),
|
||||
"third_party_path"_a =
|
||||
TO_UTF8( SCRIPTING::PyPluginsPath( SCRIPTING::PATH_TYPE::THIRDPARTY ) ) );
|
||||
|
||||
pybind11::exec( R"(
|
||||
import sys
|
||||
import pcbnew
|
||||
pcbnew.LoadPlugins( sys_path, user_path, third_party_path )
|
||||
)", pybind11::globals(), locals );
|
||||
)",
|
||||
pybind11::globals(), locals );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -459,8 +459,12 @@ wxString SCRIPTING::PyScriptingPath( PATH_TYPE aPathType )
|
|||
//@todo This should this be a user configurable variable eg KISCRIPT?
|
||||
switch( aPathType )
|
||||
{
|
||||
case STOCK: path = PATHS::GetStockScriptingPath(); break;
|
||||
case USER: path = PATHS::GetUserScriptingPath(); break;
|
||||
case STOCK:
|
||||
path = PATHS::GetStockScriptingPath();
|
||||
break;
|
||||
case USER:
|
||||
path = PATHS::GetUserScriptingPath();
|
||||
break;
|
||||
case THIRDPARTY:
|
||||
const ENV_VAR_MAP& env = Pgm().GetLocalEnvVariables();
|
||||
auto it = env.find( "KICAD6_3RD_PARTY" );
|
||||
|
|