PCM: automatic check for repository updates
This commit is contained in:
parent
97d7ee1f30
commit
f4fa3b02c5
|
@ -435,6 +435,7 @@ set( COMMON_SRCS
|
|||
settings/nested_settings.cpp
|
||||
settings/parameters.cpp
|
||||
settings/settings_manager.cpp
|
||||
settings/kicad_settings.cpp
|
||||
|
||||
project/board_project_settings.cpp
|
||||
project/net_settings.cpp
|
||||
|
@ -460,6 +461,7 @@ target_link_libraries( common
|
|||
threadpool
|
||||
pybind11::embed
|
||||
compoundfilereader
|
||||
pcm_settings
|
||||
${Boost_LIBRARIES}
|
||||
${CURL_LIBRARIES}
|
||||
${wxWidgets_LIBRARIES}
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <panel_hotkeys_editor.h>
|
||||
#include <paths.h>
|
||||
#include <confirm.h>
|
||||
#include <panel_pcm_settings.h>
|
||||
#include <pgm_base.h>
|
||||
#include <settings/app_settings.h>
|
||||
#include <settings/common_settings.h>
|
||||
|
@ -1074,6 +1075,7 @@ void EDA_BASE_FRAME::OnPreferences( wxCommandEvent& event )
|
|||
book->AddSubPage( CREATE_PANEL( PANEL_DS_DISPLAY_OPTIONS ), _( "Display Options" ) );
|
||||
book->AddSubPage( CREATE_PANEL( PANEL_DS_COLORS ), _( "Colors" ) );
|
||||
|
||||
book->AddPage( new PANEL_PCM_SETTINGS( book ), _( "Plugin and Content Manager" ) );
|
||||
|
||||
// Update all of the action hotkeys. The process of loading the actions through
|
||||
// the KiFACE will only get us the default hotkeys
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "kicad_settings.h"
|
||||
#include "settings/kicad_settings.h"
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <settings/parameters.h>
|
||||
|
||||
|
@ -42,6 +42,8 @@ KICAD_SETTINGS::KICAD_SETTINGS() :
|
|||
m_params.emplace_back(
|
||||
new PARAM_LIST<wxString>( "system.open_projects", &m_OpenProjects, {} ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<int>( "system.check_for_updates", &m_updateCheck, 0 ) );
|
||||
|
||||
m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>(
|
||||
"pcm.repositories",
|
||||
[&]() -> nlohmann::json
|
||||
|
@ -77,6 +79,9 @@ KICAD_SETTINGS::KICAD_SETTINGS() :
|
|||
|
||||
m_params.emplace_back(
|
||||
new PARAM<wxString>( "pcm.last_download_dir", &m_PcmLastDownloadDir, "" ) );
|
||||
|
||||
m_params.emplace_back(
|
||||
new PARAM<bool>( "pcm.check_for_updates", &m_PcmUpdateCheck, true ) );
|
||||
}
|
||||
|
||||
|
|
@ -35,14 +35,16 @@
|
|||
BITMAP_BUTTON::BITMAP_BUTTON( wxWindow* aParent, wxWindowID aId, const wxPoint& aPos,
|
||||
const wxSize& aSize, int aStyles ) :
|
||||
wxPanel( aParent, aId, aPos, aSize, aStyles ),
|
||||
m_isRadioButton( false ),
|
||||
m_buttonState( 0 ),
|
||||
m_padding( 0 ),
|
||||
m_acceptDraggedInClicks( false )
|
||||
m_isRadioButton( false ), m_buttonState( 0 ), m_padding( 0 ),
|
||||
m_acceptDraggedInClicks( false ), m_showBadge( false ),
|
||||
m_badgeColor( wxColor( 210, 0, 0, 0 ) ), // dark red
|
||||
m_badgeTextColor( wxColor( wxT( "white" ) ) )
|
||||
{
|
||||
if( aSize == wxDefaultSize )
|
||||
SetMinSize( wxButton::GetDefaultSize() + wxSize( m_padding * 2, m_padding * 2) );
|
||||
|
||||
m_badgeFont = GetFont().Smaller().MakeBold();
|
||||
|
||||
setupEvents();
|
||||
}
|
||||
|
||||
|
@ -254,6 +256,23 @@ void BITMAP_BUTTON::OnPaint( wxPaintEvent& aEvent )
|
|||
// Draw the bitmap with the upper-left corner offset by the padding
|
||||
if( bmp.IsOk() )
|
||||
dc.DrawBitmap( bmp, m_padding, m_padding, true );
|
||||
|
||||
// Draw the badge
|
||||
if( m_showBadge )
|
||||
{
|
||||
dc.SetFont( m_badgeFont );
|
||||
|
||||
wxSize box_size = dc.GetTextExtent( m_badgeText ) + wxSize( 6, 2 );
|
||||
wxSize box_offset = box_size + wxSize( m_padding - 2, m_padding );
|
||||
wxSize text_offset = box_offset - wxSize( 3, 1 );
|
||||
|
||||
dc.SetPen( wxPen( m_badgeColor ) );
|
||||
dc.SetBrush( wxBrush( m_badgeColor ) );
|
||||
dc.DrawRoundedRectangle( rect.GetRightBottom() - box_offset, box_size, -0.25 );
|
||||
|
||||
dc.SetTextForeground( m_badgeTextColor );
|
||||
dc.DrawText( m_badgeText, rect.GetRightBottom() - text_offset );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -36,11 +36,31 @@ public:
|
|||
|
||||
int m_LeftWinWidth;
|
||||
|
||||
/**
|
||||
* @brief General setting for various update checks
|
||||
*
|
||||
* A one time popup asks user to allow/disallow update checks on startup.
|
||||
* This is currently used by PCM.
|
||||
*
|
||||
* See enum below for meaning of values.
|
||||
*/
|
||||
int m_updateCheck;
|
||||
|
||||
enum UPDATE_CHECK {
|
||||
UNINITIALIZED = 0,
|
||||
NOT_ALLOWED = 1,
|
||||
ALLOWED = 2
|
||||
};
|
||||
|
||||
std::vector<wxString> m_OpenProjects;
|
||||
|
||||
std::vector<std::pair<wxString, wxString>> m_PcmRepositories;
|
||||
wxString m_PcmLastDownloadDir;
|
||||
|
||||
// This controls background update check for PCM.
|
||||
// It is set according to m_updateCheck on first start.
|
||||
bool m_PcmUpdateCheck;
|
||||
|
||||
protected:
|
||||
virtual std::string getLegacyFrameName() const override { return "KicadFrame"; }
|
||||
};
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/colour.h>
|
||||
|
||||
|
||||
/**
|
||||
|
@ -104,6 +105,16 @@ public:
|
|||
*/
|
||||
void AcceptDragInAsClick( bool aAcceptDragIn = true );
|
||||
|
||||
void SetShowBadge( bool aShowBadge ) { m_showBadge = aShowBadge; }
|
||||
|
||||
void SetBadgeText( const wxString& aText ) { m_badgeText = aText; }
|
||||
|
||||
void SetBadgeColors( const wxColor& aBadgeColor, const wxColor& aBadgeTextColor )
|
||||
{
|
||||
m_badgeColor = aBadgeColor;
|
||||
m_badgeTextColor = aBadgeTextColor;
|
||||
}
|
||||
|
||||
protected:
|
||||
void setupEvents();
|
||||
|
||||
|
@ -135,6 +146,11 @@ private:
|
|||
wxBitmap m_disabledBitmap;
|
||||
|
||||
bool m_isRadioButton;
|
||||
bool m_showBadge;
|
||||
wxString m_badgeText;
|
||||
wxColor m_badgeColor;
|
||||
wxColor m_badgeTextColor;
|
||||
wxFont m_badgeFont;
|
||||
int m_buttonState;
|
||||
int m_padding;
|
||||
wxSize m_unadjustedMinSize;
|
||||
|
|
|
@ -24,7 +24,6 @@ set( KICAD_SRCS
|
|||
import_project.cpp
|
||||
kicad.cpp
|
||||
kicad_manager_frame.cpp
|
||||
kicad_settings.cpp
|
||||
menubar.cpp
|
||||
project_template.cpp
|
||||
project_tree_pane.cpp
|
||||
|
|
|
@ -44,6 +44,8 @@ PANEL_KICAD_LAUNCHER::PANEL_KICAD_LAUNCHER( wxWindow* aParent ) :
|
|||
|
||||
void PANEL_KICAD_LAUNCHER::CreateLaunchers()
|
||||
{
|
||||
m_frame->SetPcmButton( nullptr );
|
||||
|
||||
if( m_toolsSizer->GetRows() > 0 )
|
||||
{
|
||||
m_toolsSizer->Clear( true );
|
||||
|
@ -119,6 +121,8 @@ void PANEL_KICAD_LAUNCHER::CreateLaunchers()
|
|||
help->Disable();
|
||||
label->Disable();
|
||||
}
|
||||
|
||||
return btn;
|
||||
};
|
||||
|
||||
addLauncher( KICAD_MANAGER_ACTIONS::editSchematic,
|
||||
|
@ -154,10 +158,14 @@ void PANEL_KICAD_LAUNCHER::CreateLaunchers()
|
|||
_( "Edit drawing sheet borders and title blocks for use in schematics and PCB "
|
||||
"designs" ) );
|
||||
|
||||
addLauncher( KICAD_MANAGER_ACTIONS::showPluginManager,
|
||||
KiScaledBitmap( BITMAPS::icon_pcm, this, 48, true ),
|
||||
_( "Manage downloadable packages from KiCad and 3rd party repositories" ),
|
||||
( KIPLATFORM::POLICY::GetPolicyState( POLICY_KEY_PCM ) != KIPLATFORM::POLICY::STATE::DISABLED ) );
|
||||
BITMAP_BUTTON* bb =
|
||||
addLauncher( KICAD_MANAGER_ACTIONS::showPluginManager,
|
||||
KiScaledBitmap( BITMAPS::icon_pcm, this, 48, true ),
|
||||
_( "Manage downloadable packages from KiCad and 3rd party repositories" ),
|
||||
( KIPLATFORM::POLICY::GetPolicyState( POLICY_KEY_PCM )
|
||||
!= KIPLATFORM::POLICY::STATE::DISABLED ) );
|
||||
|
||||
m_frame->SetPcmButton( bb );
|
||||
|
||||
Layout();
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <paths.h>
|
||||
#include <richio.h>
|
||||
#include <settings/settings_manager.h>
|
||||
#include <settings/kicad_settings.h>
|
||||
#include <systemdirsappend.h>
|
||||
#include <trace_helpers.h>
|
||||
#include <wildcards_and_files_ext.h>
|
||||
|
@ -49,7 +50,6 @@
|
|||
|
||||
#include "pgm_kicad.h"
|
||||
#include "kicad_manager_frame.h"
|
||||
#include "kicad_settings.h"
|
||||
|
||||
#include <kiplatform/app.h>
|
||||
#include <kiplatform/environment.h>
|
||||
|
|
|
@ -32,7 +32,9 @@
|
|||
#include <dialogs/panel_kicad_launcher.h>
|
||||
#include <eda_base_frame.h>
|
||||
#include <filehistory.h>
|
||||
#include <policy_keys.h>
|
||||
#include <kiplatform/app.h>
|
||||
#include <kiplatform/policy.h>
|
||||
#include <kicad_build_version.h>
|
||||
#include <kiway.h>
|
||||
#include <kiway_express.h>
|
||||
|
@ -65,7 +67,7 @@
|
|||
#endif
|
||||
|
||||
#include "kicad_manager_frame.h"
|
||||
#include "kicad_settings.h"
|
||||
#include "settings/kicad_settings.h"
|
||||
|
||||
|
||||
#define SEP() wxFileName::GetPathSeparator()
|
||||
|
@ -124,7 +126,7 @@ KICAD_MANAGER_FRAME::KICAD_MANAGER_FRAME( wxWindow* parent, const wxString& titl
|
|||
wxXmlDocument dummy;
|
||||
|
||||
// Create the status line (bottom of the frame). Left half is for project name; right half
|
||||
// is for Reporter (currently used by archiver/unarchiver).
|
||||
// is for Reporter (currently used by archiver/unarchiver and PCM).
|
||||
CreateStatusBar( 2 );
|
||||
GetStatusBar()->SetFont( KIUI::GetStatusFont( this ) );
|
||||
|
||||
|
@ -153,6 +155,28 @@ KICAD_MANAGER_FRAME::KICAD_MANAGER_FRAME( wxWindow* parent, const wxString& titl
|
|||
// Load the settings
|
||||
LoadSettings( config() );
|
||||
|
||||
m_pcmButton = nullptr;
|
||||
m_pcmUpdateCount = 0;
|
||||
m_pcm = std::make_shared<PLUGIN_CONTENT_MANAGER>(
|
||||
[this]( int aUpdateCount )
|
||||
{
|
||||
m_pcmUpdateCount = aUpdateCount;
|
||||
CallAfter(
|
||||
[this]()
|
||||
{
|
||||
updatePcmButtonBadge();
|
||||
} );
|
||||
},
|
||||
[this]( const wxString aText )
|
||||
{
|
||||
CallAfter(
|
||||
[aText, this]()
|
||||
{
|
||||
SetStatusText( aText, 1 );
|
||||
} );
|
||||
} );
|
||||
m_pcm->SetRepositoryList( kicadSettings()->m_PcmRepositories );
|
||||
|
||||
// Left window: is the box which display tree project
|
||||
m_leftWin = new PROJECT_TREE_PANE( this );
|
||||
|
||||
|
@ -215,6 +239,8 @@ KICAD_MANAGER_FRAME::~KICAD_MANAGER_FRAME()
|
|||
if( m_toolManager )
|
||||
m_toolManager->ShutdownAllTools();
|
||||
|
||||
m_pcm->StopBackgroundUpdate();
|
||||
|
||||
delete m_actions;
|
||||
delete m_toolManager;
|
||||
delete m_toolDispatcher;
|
||||
|
@ -656,6 +682,11 @@ void KICAD_MANAGER_FRAME::ShowChangedLanguage()
|
|||
void KICAD_MANAGER_FRAME::CommonSettingsChanged( bool aEnvVarsChanged, bool aTextVarsChanged )
|
||||
{
|
||||
EDA_BASE_FRAME::CommonSettingsChanged( aEnvVarsChanged, aTextVarsChanged );
|
||||
|
||||
if( aEnvVarsChanged )
|
||||
{
|
||||
m_pcm->ReadEnvVar();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -792,4 +823,55 @@ void KICAD_MANAGER_FRAME::OnIdle( wxIdleEvent& aEvent )
|
|||
|
||||
// clear file states regardless if we opened windows or not due to setting
|
||||
Prj().GetLocalSettings().ClearFileState();
|
||||
|
||||
KICAD_SETTINGS* settings = kicadSettings();
|
||||
|
||||
if( settings->m_updateCheck == KICAD_SETTINGS::UPDATE_CHECK::UNINITIALIZED )
|
||||
{
|
||||
if( wxMessageBox( _( "Would you like to automatically check for updates on startup?" ),
|
||||
_( "Check for updates" ), wxICON_QUESTION | wxYES_NO, this )
|
||||
== wxYES )
|
||||
{
|
||||
settings->m_updateCheck = KICAD_SETTINGS::UPDATE_CHECK::ALLOWED;
|
||||
settings->m_PcmUpdateCheck = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
settings->m_updateCheck = KICAD_SETTINGS::UPDATE_CHECK::NOT_ALLOWED;
|
||||
settings->m_PcmUpdateCheck = false;
|
||||
}
|
||||
}
|
||||
|
||||
if( KIPLATFORM::POLICY::GetPolicyState( POLICY_KEY_PCM ) != KIPLATFORM::POLICY::STATE::DISABLED
|
||||
&& settings->m_PcmUpdateCheck )
|
||||
{
|
||||
m_pcm->RunBackgroundUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void KICAD_MANAGER_FRAME::SetPcmButton( BITMAP_BUTTON* aButton )
|
||||
{
|
||||
m_pcmButton = aButton;
|
||||
|
||||
updatePcmButtonBadge();
|
||||
}
|
||||
|
||||
|
||||
void KICAD_MANAGER_FRAME::updatePcmButtonBadge()
|
||||
{
|
||||
if( m_pcmButton )
|
||||
{
|
||||
if( m_pcmUpdateCount > 0 )
|
||||
{
|
||||
m_pcmButton->SetShowBadge( true );
|
||||
m_pcmButton->SetBadgeText( wxString::Format( "%d", m_pcmUpdateCount ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pcmButton->SetShowBadge( false );
|
||||
}
|
||||
|
||||
m_pcmButton->Refresh();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#include <wx/process.h>
|
||||
#include <kiway_player.h>
|
||||
#include <wx/dnd.h>
|
||||
#include "pcm.h"
|
||||
#include "widgets/bitmap_button.h"
|
||||
|
||||
class PROJECT_TREE;
|
||||
class PROJECT_TREE_PANE;
|
||||
|
@ -151,6 +153,10 @@ public:
|
|||
|
||||
wxWindow* GetToolCanvas() const override;
|
||||
|
||||
std::shared_ptr<PLUGIN_CONTENT_MANAGER> GetPcm() { return m_pcm; };
|
||||
|
||||
void SetPcmButton( BITMAP_BUTTON* aButton );
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
protected:
|
||||
|
@ -176,15 +182,19 @@ private:
|
|||
|
||||
void language_change( wxCommandEvent& event );
|
||||
|
||||
bool m_openSavedWindows;
|
||||
void updatePcmButtonBadge();
|
||||
|
||||
bool m_openSavedWindows;
|
||||
int m_leftWinWidth;
|
||||
bool m_active_project;
|
||||
|
||||
private:
|
||||
PROJECT_TREE_PANE* m_leftWin;
|
||||
PANEL_KICAD_LAUNCHER* m_launcher;
|
||||
ACTION_TOOLBAR* m_mainToolBar;
|
||||
|
||||
int m_leftWinWidth;
|
||||
bool m_active_project;
|
||||
std::shared_ptr<PLUGIN_CONTENT_MANAGER> m_pcm;
|
||||
BITMAP_BUTTON* m_pcmButton;
|
||||
int m_pcmUpdateCount;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -8,9 +8,9 @@ include_directories( BEFORE ${INC_BEFORE} )
|
|||
|
||||
add_definitions( -DPCM )
|
||||
|
||||
include_directories(
|
||||
${CMAKE_SOURCE_DIR}/common
|
||||
${CMAKE_SOURCE_DIR}/kicad
|
||||
set ( PCM_SETTINGS_SRCS
|
||||
dialogs/panel_pcm_settings_base.cpp
|
||||
dialogs/panel_pcm_settings.cpp
|
||||
)
|
||||
|
||||
set ( PCM_DLG_SRCS
|
||||
|
@ -48,6 +48,21 @@ target_link_libraries( pcm
|
|||
nlohmann_json_schema_validator
|
||||
)
|
||||
|
||||
add_library( pcm_settings STATIC
|
||||
${PCM_SETTINGS_SRCS}
|
||||
)
|
||||
|
||||
# This is a circular dependency but it's not a problem for static libs.
|
||||
# Refactoring this would need separating kicad_settings, settings manager
|
||||
# and pgm_base out of common.
|
||||
target_link_libraries( pcm_settings common )
|
||||
|
||||
target_include_directories(
|
||||
pcm_settings
|
||||
PUBLIC dialogs
|
||||
PRIVATE $<TARGET_PROPERTY:common,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
)
|
||||
|
||||
INSTALL( DIRECTORY
|
||||
schemas
|
||||
DESTINATION ${KICAD_DATA}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "bitmaps/bitmap_types.h"
|
||||
#include "bitmaps/bitmaps_list.h"
|
||||
#include "grid_tricks.h"
|
||||
#include "kicad_settings.h"
|
||||
#include "settings/kicad_settings.h"
|
||||
#include "widgets/wx_grid.h"
|
||||
|
||||
|
||||
|
|
|
@ -27,9 +27,9 @@
|
|||
#include "dialog_pcm.h"
|
||||
#include "grid_tricks.h"
|
||||
#include "ki_exception.h"
|
||||
#include "kicad_settings.h"
|
||||
#include "pcm_task_manager.h"
|
||||
#include "pgm_base.h"
|
||||
#include "settings/kicad_settings.h"
|
||||
#include "settings/settings_manager.h"
|
||||
#include "thread"
|
||||
#include "widgets/wx_grid.h"
|
||||
|
@ -53,11 +53,13 @@ static std::vector<std::pair<PCM_PACKAGE_TYPE, wxString>> PACKAGE_TYPE_LIST = {
|
|||
};
|
||||
|
||||
|
||||
DIALOG_PCM::DIALOG_PCM( wxWindow* parent ) : DIALOG_PCM_BASE( parent )
|
||||
DIALOG_PCM::DIALOG_PCM( wxWindow* parent, std::shared_ptr<PLUGIN_CONTENT_MANAGER> pcm ) :
|
||||
DIALOG_PCM_BASE( parent ), m_pcm( pcm )
|
||||
{
|
||||
m_defaultBitmap = KiBitmap( BITMAPS::icon_pcm );
|
||||
|
||||
m_pcm = std::make_shared<PLUGIN_CONTENT_MANAGER>( this );
|
||||
m_pcm->SetDialogWindow( this );
|
||||
m_pcm->StopBackgroundUpdate();
|
||||
|
||||
m_gridPendingActions->PushEventHandler( new GRID_TRICKS( m_gridPendingActions ) );
|
||||
|
||||
|
@ -142,11 +144,6 @@ DIALOG_PCM::DIALOG_PCM( wxWindow* parent ) : DIALOG_PCM_BASE( parent )
|
|||
m_sdbSizer1Cancel->Bind( wxEVT_UPDATE_UI, &DIALOG_PCM::OnUpdateEventButtons, this );
|
||||
m_sdbSizer1Apply->Bind( wxEVT_UPDATE_UI, &DIALOG_PCM::OnUpdateEventButtons, this );
|
||||
|
||||
SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
|
||||
KICAD_SETTINGS* app_settings = mgr.GetAppSettings<KICAD_SETTINGS>();
|
||||
|
||||
m_pcm->SetRepositoryList( app_settings->m_PcmRepositories );
|
||||
|
||||
setRepositoryListFromPcm();
|
||||
|
||||
for( int col = 0; col < m_gridPendingActions->GetNumberCols(); col++ )
|
||||
|
@ -165,6 +162,10 @@ DIALOG_PCM::DIALOG_PCM( wxWindow* parent ) : DIALOG_PCM_BASE( parent )
|
|||
|
||||
DIALOG_PCM::~DIALOG_PCM()
|
||||
{
|
||||
m_pcm->SaveInstalledPackages();
|
||||
m_pcm->SetDialogWindow( nullptr );
|
||||
m_pcm->RunBackgroundUpdate();
|
||||
|
||||
m_gridPendingActions->PopEventHandler( true );
|
||||
}
|
||||
|
||||
|
@ -392,6 +393,12 @@ void DIALOG_PCM::setInstalledPackages()
|
|||
else
|
||||
package_data.bitmap = &m_defaultBitmap;
|
||||
|
||||
package_data.state =
|
||||
m_pcm->GetPackageState( entry.repository_id, entry.package.identifier );
|
||||
|
||||
if( package_data.state == PPS_UPDATE_AVAILABLE )
|
||||
package_data.update_version = m_pcm->GetPackageUpdateVersion( entry.package );
|
||||
|
||||
package_list.emplace_back( package_data );
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ class DIALOG_PCM : public DIALOG_PCM_BASE
|
|||
{
|
||||
public:
|
||||
/** Constructor */
|
||||
DIALOG_PCM( wxWindow* parent );
|
||||
DIALOG_PCM( wxWindow* parent, std::shared_ptr<PLUGIN_CONTENT_MANAGER> pcm );
|
||||
~DIALOG_PCM();
|
||||
|
||||
///< Closes the window, asks user confirmation if there are pending actions
|
||||
|
|
|
@ -21,10 +21,10 @@
|
|||
#include "panel_packages_view.h"
|
||||
#include <grid_tricks.h>
|
||||
#include <html_window.h>
|
||||
#include <kicad_settings.h>
|
||||
#include <pgm_base.h>
|
||||
#include <settings/common_settings.h>
|
||||
#include <settings/settings_manager.h>
|
||||
#include <settings/kicad_settings.h>
|
||||
#include <string_utils.h>
|
||||
#include <widgets/wx_panel.h>
|
||||
#include <widgets/wx_splitter_window.h>
|
||||
|
@ -113,6 +113,7 @@ void PANEL_PACKAGES_VIEW::ClearData()
|
|||
unsetPackageDetails();
|
||||
|
||||
m_currentSelected = nullptr;
|
||||
m_updateablePackages.clear();
|
||||
m_packagePanels.clear();
|
||||
m_packageInitialOrder.clear();
|
||||
m_packageListWindow->GetSizer()->Clear( true ); // Delete panels
|
||||
|
@ -148,9 +149,13 @@ void PANEL_PACKAGES_VIEW::SetData( const std::vector<PACKAGE_VIEW_DATA>& aPackag
|
|||
|
||||
m_packagePanels.insert( { data.package.identifier, package_panel } );
|
||||
m_packageInitialOrder.push_back( data.package.identifier );
|
||||
|
||||
if( data.state == PPS_UPDATE_AVAILABLE )
|
||||
m_updateablePackages.insert( data.package.identifier );
|
||||
}
|
||||
|
||||
updatePackageList();
|
||||
updateCommonState();
|
||||
}
|
||||
|
||||
|
||||
|
@ -426,7 +431,7 @@ bool PANEL_PACKAGES_VIEW::canRunAction() const
|
|||
|
||||
|
||||
void PANEL_PACKAGES_VIEW::SetPackageState( const wxString& aPackageId,
|
||||
const PCM_PACKAGE_STATE aState ) const
|
||||
const PCM_PACKAGE_STATE aState )
|
||||
{
|
||||
auto it = m_packagePanels.find( aPackageId );
|
||||
|
||||
|
@ -439,6 +444,17 @@ void PANEL_PACKAGES_VIEW::SetPackageState( const wxString& aPackageId,
|
|||
wxMouseEvent dummy;
|
||||
m_currentSelected->OnClick( dummy );
|
||||
}
|
||||
|
||||
if( aState == PPS_UPDATE_AVAILABLE )
|
||||
{
|
||||
m_updateablePackages.insert( aPackageId );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_updateablePackages.erase( aPackageId );
|
||||
}
|
||||
|
||||
updateCommonState();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -760,3 +776,31 @@ void PANEL_PACKAGES_VIEW::SetSashOnIdle( wxIdleEvent& aEvent )
|
|||
m_splitter1->Disconnect( wxEVT_IDLE, wxIdleEventHandler( PANEL_PACKAGES_VIEW::SetSashOnIdle ),
|
||||
NULL, this );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PACKAGES_VIEW::updateCommonState()
|
||||
{
|
||||
m_buttonUpdateAll->Enable( m_updateablePackages.size() > 0 );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PACKAGES_VIEW::OnUpdateAllClicked( wxCommandEvent& event )
|
||||
{
|
||||
// The map will be modified by the callback so we copy the list here
|
||||
std::vector<wxString> packages;
|
||||
|
||||
std::copy( m_updateablePackages.begin(), m_updateablePackages.end(),
|
||||
std::back_inserter( packages ) );
|
||||
|
||||
for( const wxString& pkg_id : packages )
|
||||
{
|
||||
auto it = m_packagePanels.find( pkg_id );
|
||||
|
||||
if( it != m_packagePanels.end() )
|
||||
{
|
||||
const PACKAGE_VIEW_DATA& data = it->second->GetPackageData();
|
||||
|
||||
m_actionCallback( data, PPA_UPDATE, data.update_version );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ public:
|
|||
* @param aPackageId id of the package
|
||||
* @param aState new state
|
||||
*/
|
||||
void SetPackageState( const wxString& aPackageId, const PCM_PACKAGE_STATE aState ) const;
|
||||
void SetPackageState( const wxString& aPackageId, const PCM_PACKAGE_STATE aState );
|
||||
|
||||
///< Destroys package panels
|
||||
void ClearData();
|
||||
|
@ -83,6 +83,9 @@ public:
|
|||
///< Replacement of wxFormBuilder's ill-advised m_splitter1OnIdle
|
||||
void SetSashOnIdle( wxIdleEvent& );
|
||||
|
||||
///< Enqueues all available package updates
|
||||
void OnUpdateAllClicked( wxCommandEvent& event ) override;
|
||||
|
||||
private:
|
||||
///< Updates package listing according to search term
|
||||
void updatePackageList();
|
||||
|
@ -90,6 +93,9 @@ private:
|
|||
///< Updates buttons below the package details: Download and Install
|
||||
void updateDetailsButtons();
|
||||
|
||||
///< Called when package state changes, currently used to calculate Update All button state
|
||||
void updateCommonState();
|
||||
|
||||
///< Updates details panel
|
||||
void setPackageDetails( const PACKAGE_VIEW_DATA& aPackageData );
|
||||
|
||||
|
@ -113,6 +119,7 @@ private:
|
|||
std::unordered_map<wxString, PANEL_PACKAGE*> m_packagePanels;
|
||||
std::vector<wxString> m_packageInitialOrder;
|
||||
PANEL_PACKAGE* m_currentSelected;
|
||||
std::unordered_set<wxString> m_updateablePackages;
|
||||
std::shared_ptr<PLUGIN_CONTENT_MANAGER> m_pcm;
|
||||
|
||||
enum PACKAGE_VERSIONS_GRID_COLUMNS
|
||||
|
|
|
@ -25,12 +25,21 @@ PANEL_PACKAGES_VIEW_BASE::PANEL_PACKAGES_VIEW_BASE( wxWindow* parent, wxWindowID
|
|||
wxBoxSizer* bPanelListSizer;
|
||||
bPanelListSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxBoxSizer* bSizer8;
|
||||
bSizer8 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_searchCtrl = new wxSearchCtrl( m_panelList, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
#ifndef __WXMAC__
|
||||
m_searchCtrl->ShowSearchButton( true );
|
||||
#endif
|
||||
m_searchCtrl->ShowCancelButton( false );
|
||||
bPanelListSizer->Add( m_searchCtrl, 0, wxEXPAND|wxALL, 5 );
|
||||
bSizer8->Add( m_searchCtrl, 1, wxEXPAND|wxALL, 5 );
|
||||
|
||||
m_buttonUpdateAll = new wxButton( m_panelList, wxID_ANY, _("Update All"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizer8->Add( m_buttonUpdateAll, 0, wxBOTTOM|wxRIGHT|wxTOP, 5 );
|
||||
|
||||
|
||||
bPanelListSizer->Add( bSizer8, 0, wxEXPAND, 5 );
|
||||
|
||||
m_packageListWindow = new wxScrolledWindow( m_panelList, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE|wxFULL_REPAINT_ON_RESIZE|wxVSCROLL );
|
||||
m_packageListWindow->SetScrollRate( 5, 5 );
|
||||
|
@ -137,6 +146,7 @@ PANEL_PACKAGES_VIEW_BASE::PANEL_PACKAGES_VIEW_BASE( wxWindow* parent, wxWindowID
|
|||
bSizer1->Fit( this );
|
||||
|
||||
// Connect Events
|
||||
m_buttonUpdateAll->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PACKAGES_VIEW_BASE::OnUpdateAllClicked ), NULL, this );
|
||||
m_infoScrollWindow->Connect( wxEVT_SIZE, wxSizeEventHandler( PANEL_PACKAGES_VIEW_BASE::OnSizeInfoBox ), NULL, this );
|
||||
m_infoText->Connect( wxEVT_COMMAND_HTML_LINK_CLICKED, wxHtmlLinkEventHandler( PANEL_PACKAGES_VIEW_BASE::OnURLClicked ), NULL, this );
|
||||
m_infoText->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PACKAGES_VIEW_BASE::OnInfoMouseWheel ), NULL, this );
|
||||
|
@ -149,6 +159,7 @@ PANEL_PACKAGES_VIEW_BASE::PANEL_PACKAGES_VIEW_BASE( wxWindow* parent, wxWindowID
|
|||
PANEL_PACKAGES_VIEW_BASE::~PANEL_PACKAGES_VIEW_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
m_buttonUpdateAll->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PACKAGES_VIEW_BASE::OnUpdateAllClicked ), NULL, this );
|
||||
m_infoScrollWindow->Disconnect( wxEVT_SIZE, wxSizeEventHandler( PANEL_PACKAGES_VIEW_BASE::OnSizeInfoBox ), NULL, this );
|
||||
m_infoText->Disconnect( wxEVT_COMMAND_HTML_LINK_CLICKED, wxHtmlLinkEventHandler( PANEL_PACKAGES_VIEW_BASE::OnURLClicked ), NULL, this );
|
||||
m_infoText->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PACKAGES_VIEW_BASE::OnInfoMouseWheel ), NULL, this );
|
||||
|
|
|
@ -177,67 +177,152 @@
|
|||
<property name="permission">none</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND|wxALL</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxSearchCtrl" 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="cancel_button">0</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>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<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="search_button">1</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>
|
||||
<property name="name">bSizer8</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|wxALL</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxSearchCtrl" 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="cancel_button">0</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_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="search_button">1</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>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxBOTTOM|wxRIGHT|wxTOP</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="auth_needed">0</property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="bitmap"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="current"></property>
|
||||
<property name="default">0</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="disabled"></property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="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">Update All</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_buttonUpdateAll</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">OnUpdateAllClicked</event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
|
|
|
@ -21,16 +21,16 @@ class WX_PANEL;
|
|||
#include <wx/font.h>
|
||||
#include <wx/colour.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/icon.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/scrolwin.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/html/htmlwin.h>
|
||||
#include <wx/grid.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/icon.h>
|
||||
#include <wx/splitter.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
@ -47,6 +47,7 @@ class PANEL_PACKAGES_VIEW_BASE : public wxPanel
|
|||
WX_SPLITTER_WINDOW* m_splitter1;
|
||||
WX_PANEL* m_panelList;
|
||||
wxSearchCtrl* m_searchCtrl;
|
||||
wxButton* m_buttonUpdateAll;
|
||||
wxScrolledWindow* m_packageListWindow;
|
||||
wxPanel* m_panelDetails;
|
||||
wxScrolledWindow* m_infoScrollWindow;
|
||||
|
@ -58,6 +59,7 @@ class PANEL_PACKAGES_VIEW_BASE : public wxPanel
|
|||
wxButton* m_buttonAction;
|
||||
|
||||
// Virtual event handlers, override them in your derived class
|
||||
virtual void OnUpdateAllClicked( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnSizeInfoBox( wxSizeEvent& event ) { event.Skip(); }
|
||||
virtual void OnURLClicked( wxHtmlLinkEvent& event ) { event.Skip(); }
|
||||
virtual void OnInfoMouseWheel( wxMouseEvent& event ) { event.Skip(); }
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2022 Andrew Lutsenko, anlutsenko at gmail dot com
|
||||
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "panel_pcm_settings.h"
|
||||
|
||||
#include <pgm_base.h>
|
||||
#include <settings/kicad_settings.h>
|
||||
#include <settings/settings_manager.h>
|
||||
|
||||
PANEL_PCM_SETTINGS::PANEL_PCM_SETTINGS( wxWindow* parent ) : PANEL_PCM_SETTINGS_BASE( parent )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool PANEL_PCM_SETTINGS::TransferDataToWindow()
|
||||
{
|
||||
SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
|
||||
KICAD_SETTINGS* settings = mgr.GetAppSettings<KICAD_SETTINGS>();
|
||||
|
||||
m_updateCheck->SetValue( settings->m_PcmUpdateCheck );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PANEL_PCM_SETTINGS::TransferDataFromWindow()
|
||||
{
|
||||
SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
|
||||
KICAD_SETTINGS* settings = mgr.GetAppSettings<KICAD_SETTINGS>();
|
||||
|
||||
settings->m_PcmUpdateCheck = m_updateCheck->GetValue();
|
||||
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2022 Andrew Lutsenko, anlutsenko at gmail dot com
|
||||
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef PANEL_PCM_SETTINGS_H_
|
||||
#define PANEL_PCM_SETTINGS_H_
|
||||
|
||||
#include "panel_pcm_settings_base.h"
|
||||
|
||||
class PANEL_PCM_SETTINGS : public PANEL_PCM_SETTINGS_BASE
|
||||
{
|
||||
public:
|
||||
PANEL_PCM_SETTINGS( wxWindow* parent );
|
||||
|
||||
bool TransferDataToWindow() override;
|
||||
bool TransferDataFromWindow() override;
|
||||
};
|
||||
|
||||
#endif // PANEL_PCM_SETTINGS_H_
|
|
@ -0,0 +1,28 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "panel_pcm_settings_base.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PANEL_PCM_SETTINGS_BASE::PANEL_PCM_SETTINGS_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 );
|
||||
|
||||
m_updateCheck = new wxCheckBox( this, wxID_ANY, _("Check for package updates on startup"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_updateCheck->SetValue(true);
|
||||
bSizer1->Add( m_updateCheck, 0, wxALL, 5 );
|
||||
|
||||
|
||||
this->SetSizer( bSizer1 );
|
||||
this->Layout();
|
||||
}
|
||||
|
||||
PANEL_PCM_SETTINGS_BASE::~PANEL_PCM_SETTINGS_BASE()
|
||||
{
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
<wxFormBuilder_Project>
|
||||
<FileVersion major="1" minor="16" />
|
||||
<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">panel_pcm_settings_base</property>
|
||||
<property name="first_id">1000</property>
|
||||
<property name="help_provider">none</property>
|
||||
<property name="image_path_wrapper_function_name"></property>
|
||||
<property name="indent_with_spaces"></property>
|
||||
<property name="internationalize">1</property>
|
||||
<property name="name">panel_pcm_settings_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_array_enum">0</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_PCM_SETTINGS_BASE</property>
|
||||
<property name="pos"></property>
|
||||
<property name="size">500,300</property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="two_step_creation">0</property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style">wxTAB_TRAVERSAL</property>
|
||||
<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">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">1</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">Check for package updates on startup</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_updateCheck</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>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</wxFormBuilder_Project>
|
|
@ -0,0 +1,42 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3)
|
||||
// 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/string.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/font.h>
|
||||
#include <wx/colour.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/panel.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class PANEL_PCM_SETTINGS_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class PANEL_PCM_SETTINGS_BASE : public wxPanel
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxCheckBox* m_updateCheck;
|
||||
|
||||
public:
|
||||
|
||||
PANEL_PCM_SETTINGS_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_PCM_SETTINGS_BASE();
|
||||
|
||||
};
|
||||
|
|
@ -61,16 +61,48 @@ class THROWING_ERROR_HANDLER : public nlohmann::json_schema::error_handler
|
|||
};
|
||||
|
||||
|
||||
PLUGIN_CONTENT_MANAGER::PLUGIN_CONTENT_MANAGER( wxWindow* aParent ) : m_dialog( aParent )
|
||||
class STATUS_TEXT_REPORTER : public PROGRESS_REPORTER_BASE
|
||||
{
|
||||
// Get 3rd party path
|
||||
const ENV_VAR_MAP& env = Pgm().GetLocalEnvVariables();
|
||||
auto it = env.find( "KICAD6_3RD_PARTY" );
|
||||
public:
|
||||
STATUS_TEXT_REPORTER( std::function<void( const wxString )> aStatusCallback ) :
|
||||
PROGRESS_REPORTER_BASE( 1 ), m_statusCallback( aStatusCallback )
|
||||
{
|
||||
}
|
||||
|
||||
if( it != env.end() && !it->second.GetValue().IsEmpty() )
|
||||
m_3rdparty_path = it->second.GetValue();
|
||||
else
|
||||
m_3rdparty_path = PATHS::GetDefault3rdPartyPath();
|
||||
void SetTitle( const wxString& aTitle ) override
|
||||
{
|
||||
m_title = aTitle;
|
||||
m_report = wxT( "" );
|
||||
}
|
||||
|
||||
void Report( const wxString& aMessage ) override
|
||||
{
|
||||
m_report = wxString::Format( ": %s", aMessage );
|
||||
}
|
||||
|
||||
void Cancel() { m_cancelled.store( true ); }
|
||||
|
||||
private:
|
||||
bool updateUI() override
|
||||
{
|
||||
m_statusCallback( wxString::Format( "%s%s", m_title, m_report ) );
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::function<void( const wxString )> m_statusCallback;
|
||||
|
||||
wxString m_title;
|
||||
wxString m_report;
|
||||
};
|
||||
|
||||
|
||||
PLUGIN_CONTENT_MANAGER::PLUGIN_CONTENT_MANAGER(
|
||||
std::function<void( int )> aAvailableUpdateCallback,
|
||||
std::function<void( const wxString )> aStatusCallback ) :
|
||||
m_dialog( nullptr ),
|
||||
m_availableUpdateCallback( aAvailableUpdateCallback ), m_statusCallback( aStatusCallback )
|
||||
{
|
||||
ReadEnvVar();
|
||||
|
||||
// Read and store pcm schema
|
||||
wxFileName schema_file( PATHS::GetStockDataPath( true ), "pcm.v1.schema.json" );
|
||||
|
@ -185,9 +217,22 @@ PLUGIN_CONTENT_MANAGER::PLUGIN_CONTENT_MANAGER( wxWindow* aParent ) : m_dialog(
|
|||
}
|
||||
|
||||
|
||||
void PLUGIN_CONTENT_MANAGER::ReadEnvVar()
|
||||
{
|
||||
// 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();
|
||||
}
|
||||
|
||||
|
||||
bool PLUGIN_CONTENT_MANAGER::DownloadToStream( const wxString& aUrl, std::ostream* aOutput,
|
||||
WX_PROGRESS_REPORTER* aReporter,
|
||||
const size_t aSizeLimit )
|
||||
PROGRESS_REPORTER* aReporter,
|
||||
const size_t aSizeLimit )
|
||||
{
|
||||
bool size_exceeded = false;
|
||||
|
||||
|
@ -228,10 +273,13 @@ bool PLUGIN_CONTENT_MANAGER::DownloadToStream( const wxString& aUrl, std::ostrea
|
|||
|
||||
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 ) ) );
|
||||
if( m_dialog )
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -241,7 +289,7 @@ bool PLUGIN_CONTENT_MANAGER::DownloadToStream( const wxString& aUrl, std::ostrea
|
|||
|
||||
|
||||
bool PLUGIN_CONTENT_MANAGER::FetchRepository( const wxString& aUrl, PCM_REPOSITORY& aRepository,
|
||||
WX_PROGRESS_REPORTER* aReporter )
|
||||
PROGRESS_REPORTER* aReporter )
|
||||
{
|
||||
std::stringstream repository_stream;
|
||||
|
||||
|
@ -249,7 +297,9 @@ bool PLUGIN_CONTENT_MANAGER::FetchRepository( const wxString& aUrl, PCM_REPOSITO
|
|||
|
||||
if( !DownloadToStream( aUrl, &repository_stream, aReporter, 20480 ) )
|
||||
{
|
||||
wxLogError( _( "Unable to load repository url" ) );
|
||||
if( m_dialog )
|
||||
wxLogError( _( "Unable to load repository url" ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -265,7 +315,9 @@ bool PLUGIN_CONTENT_MANAGER::FetchRepository( const wxString& aUrl, PCM_REPOSITO
|
|||
}
|
||||
catch( const std::exception& e )
|
||||
{
|
||||
wxLogError( wxString::Format( _( "Unable to parse repository:\n\n%s" ), e.what() ) );
|
||||
if( m_dialog )
|
||||
wxLogError( wxString::Format( _( "Unable to parse repository:\n\n%s" ), e.what() ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -284,7 +336,7 @@ void PLUGIN_CONTENT_MANAGER::ValidateJson( const nlohmann::json& aJson,
|
|||
bool PLUGIN_CONTENT_MANAGER::fetchPackages( const wxString& aUrl,
|
||||
const boost::optional<wxString>& aHash,
|
||||
std::vector<PCM_PACKAGE>& aPackages,
|
||||
WX_PROGRESS_REPORTER* aReporter )
|
||||
PROGRESS_REPORTER* aReporter )
|
||||
{
|
||||
std::stringstream packages_stream;
|
||||
|
||||
|
@ -292,7 +344,9 @@ bool PLUGIN_CONTENT_MANAGER::fetchPackages( const wxString& aUr
|
|||
|
||||
if( !DownloadToStream( aUrl, &packages_stream, aReporter ) )
|
||||
{
|
||||
wxLogError( _( "Unable to load repository packages url." ) );
|
||||
if( m_dialog )
|
||||
wxLogError( _( "Unable to load repository packages url." ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -300,7 +354,9 @@ bool PLUGIN_CONTENT_MANAGER::fetchPackages( const wxString& aUr
|
|||
|
||||
if( aHash && !VerifyHash( isstream, aHash.get() ) )
|
||||
{
|
||||
wxLogError( _( "Packages hash doesn't match. Repository may be corrupted." ) );
|
||||
if( m_dialog )
|
||||
wxLogError( _( "Packages hash doesn't match. Repository may be corrupted." ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -313,7 +369,10 @@ bool PLUGIN_CONTENT_MANAGER::fetchPackages( const wxString& aUr
|
|||
}
|
||||
catch( std::exception& e )
|
||||
{
|
||||
wxLogError( wxString::Format( _( "Unable to parse packages metadata:\n\n%s" ), e.what() ) );
|
||||
if( m_dialog )
|
||||
wxLogError(
|
||||
wxString::Format( _( "Unable to parse packages metadata:\n\n%s" ), e.what() ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -363,8 +422,12 @@ const bool PLUGIN_CONTENT_MANAGER::CacheRepository( const wxString& aRepositoryI
|
|||
nlohmann::json js;
|
||||
PCM_REPOSITORY current_repo;
|
||||
|
||||
std::unique_ptr<WX_PROGRESS_REPORTER> reporter =
|
||||
std::make_unique<WX_PROGRESS_REPORTER>( m_dialog, wxT( "" ), 1 );
|
||||
std::shared_ptr<PROGRESS_REPORTER> reporter;
|
||||
|
||||
if( m_dialog )
|
||||
reporter = std::make_shared<WX_PROGRESS_REPORTER>( m_dialog, wxT( "" ), 1 );
|
||||
else
|
||||
reporter = m_statusReporter;
|
||||
|
||||
if( !FetchRepository( url, current_repo, reporter.get() ) )
|
||||
return false;
|
||||
|
@ -394,8 +457,11 @@ const bool PLUGIN_CONTENT_MANAGER::CacheRepository( const wxString& aRepositoryI
|
|||
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 );
|
||||
for( size_t i = 0; i < saved_repo.package_list.size(); i++ )
|
||||
{
|
||||
preparePackage( saved_repo.package_list[i] );
|
||||
saved_repo.package_map[saved_repo.package_list[i].identifier] = i;
|
||||
}
|
||||
|
||||
m_repository_cache[aRepositoryId] = std::move( saved_repo );
|
||||
|
||||
|
@ -403,8 +469,9 @@ const bool PLUGIN_CONTENT_MANAGER::CacheRepository( const wxString& aRepositoryI
|
|||
}
|
||||
catch( ... )
|
||||
{
|
||||
wxLogError( _( "Packages cache for current repository is "
|
||||
"corrupted, it will be redownloaded." ) );
|
||||
if( m_dialog )
|
||||
wxLogError( _( "Packages cache for current repository is "
|
||||
"corrupted, it will be redownloaded." ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -418,8 +485,11 @@ const bool PLUGIN_CONTENT_MANAGER::CacheRepository( const wxString& aRepositoryI
|
|||
return false;
|
||||
}
|
||||
|
||||
std::for_each( current_repo.package_list.begin(), current_repo.package_list.end(),
|
||||
&preparePackage );
|
||||
for( size_t i = 0; i < current_repo.package_list.size(); i++ )
|
||||
{
|
||||
preparePackage( current_repo.package_list[i] );
|
||||
current_repo.package_map[current_repo.package_list[i].identifier] = i;
|
||||
}
|
||||
|
||||
repo_cache.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
|
||||
|
||||
|
@ -468,9 +538,11 @@ const bool PLUGIN_CONTENT_MANAGER::CacheRepository( const wxString& aRepositoryI
|
|||
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." ) );
|
||||
|
||||
if( m_dialog )
|
||||
wxLogError( _( "Resources file hash doesn't match and will not be used. "
|
||||
"Repository may be corrupted." ) );
|
||||
|
||||
wxRemoveFile( resource_file.GetFullPath() );
|
||||
}
|
||||
}
|
||||
|
@ -482,10 +554,70 @@ const bool PLUGIN_CONTENT_MANAGER::CacheRepository( const wxString& aRepositoryI
|
|||
}
|
||||
}
|
||||
|
||||
updateInstalledPackagesMetadata( aRepositoryId );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void PLUGIN_CONTENT_MANAGER::updateInstalledPackagesMetadata( const wxString& aRepositoryId )
|
||||
{
|
||||
const PCM_REPOSITORY& repository = getCachedRepository( aRepositoryId );
|
||||
|
||||
for( auto& entry : m_installed )
|
||||
{
|
||||
PCM_INSTALLATION_ENTRY& installation_entry = entry.second;
|
||||
|
||||
// If current package is not from this repository, skip it
|
||||
if( installation_entry.repository_id != aRepositoryId )
|
||||
continue;
|
||||
|
||||
// If current package is no longer in this repository, keep it as is
|
||||
if( repository.package_map.count( installation_entry.package.identifier ) == 0 )
|
||||
continue;
|
||||
|
||||
boost::optional<PACKAGE_VERSION> current_version;
|
||||
|
||||
auto current_version_it =
|
||||
std::find_if( installation_entry.package.versions.begin(),
|
||||
installation_entry.package.versions.end(),
|
||||
[&]( const PACKAGE_VERSION& version )
|
||||
{
|
||||
return version.version == installation_entry.current_version;
|
||||
} );
|
||||
|
||||
if( current_version_it != installation_entry.package.versions.end() )
|
||||
current_version = *current_version_it; // copy
|
||||
|
||||
// Copy repository metadata into installation entry
|
||||
installation_entry.package = repository.package_list[repository.package_map.at(
|
||||
installation_entry.package.identifier )];
|
||||
|
||||
// Insert current version if it's missing from repository metadata
|
||||
current_version_it =
|
||||
std::find_if( installation_entry.package.versions.begin(),
|
||||
installation_entry.package.versions.end(),
|
||||
[&]( const PACKAGE_VERSION& version )
|
||||
{
|
||||
return version.version == installation_entry.current_version;
|
||||
} );
|
||||
|
||||
if( current_version_it == installation_entry.package.versions.end() )
|
||||
{
|
||||
installation_entry.package.versions.emplace_back( current_version.get() );
|
||||
|
||||
// Re-sort the versions by descending version
|
||||
std::sort( installation_entry.package.versions.begin(),
|
||||
installation_entry.package.versions.end(),
|
||||
[]( const PACKAGE_VERSION& a, const PACKAGE_VERSION& b )
|
||||
{
|
||||
return a.parsed_version > b.parsed_version;
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PLUGIN_CONTENT_MANAGER::preparePackage( PCM_PACKAGE& aPackage )
|
||||
{
|
||||
// Parse package version strings
|
||||
|
@ -605,8 +737,8 @@ void PLUGIN_CONTENT_MANAGER::DiscardRepositoryCache( const wxString& aRepository
|
|||
if( m_repository_cache.count( aRepositoryId ) > 0 )
|
||||
m_repository_cache.erase( aRepositoryId );
|
||||
|
||||
wxFileName repo_cache( m_3rdparty_path, "" );
|
||||
repo_cache.AppendDir( "cache" );
|
||||
wxFileName repo_cache = wxFileName( PATHS::GetUserCachePath(), "" );
|
||||
repo_cache.AppendDir( "pcm" );
|
||||
repo_cache.AppendDir( aRepositoryId );
|
||||
|
||||
if( repo_cache.DirExists() )
|
||||
|
@ -652,16 +784,10 @@ PCM_PACKAGE_STATE PLUGIN_CONTENT_MANAGER::GetPackageState( const wxString& aRepo
|
|||
|
||||
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() )
|
||||
if( repo.package_map.count( aPackageId ) == 0 )
|
||||
return installed ? PPS_INSTALLED : PPS_UNAVAILABLE;
|
||||
|
||||
const PCM_PACKAGE& pkg = *pkg_it;
|
||||
const PCM_PACKAGE& pkg = repo.package_list[repo.package_map.at( aPackageId )];
|
||||
|
||||
if( installed )
|
||||
{
|
||||
|
@ -720,10 +846,8 @@ time_t PLUGIN_CONTENT_MANAGER::getCurrentTimestamp() const
|
|||
}
|
||||
|
||||
|
||||
PLUGIN_CONTENT_MANAGER::~PLUGIN_CONTENT_MANAGER()
|
||||
void PLUGIN_CONTENT_MANAGER::SaveInstalledPackages()
|
||||
{
|
||||
// Save current installed packages list.
|
||||
|
||||
try
|
||||
{
|
||||
nlohmann::json js;
|
||||
|
@ -920,3 +1044,84 @@ std::unordered_map<wxString, wxBitmap> PLUGIN_CONTENT_MANAGER::GetInstalledPacka
|
|||
|
||||
return bitmaps;
|
||||
}
|
||||
|
||||
|
||||
void PLUGIN_CONTENT_MANAGER::RunBackgroundUpdate()
|
||||
{
|
||||
m_statusReporter = std::make_shared<STATUS_TEXT_REPORTER>( m_statusCallback );
|
||||
|
||||
m_updateThread = std::thread(
|
||||
[this]()
|
||||
{
|
||||
if( m_installed.size() == 0 )
|
||||
return;
|
||||
|
||||
// Only fetch repositories that have installed packages
|
||||
std::unordered_set<wxString> repo_ids;
|
||||
|
||||
for( auto& entry : m_installed )
|
||||
repo_ids.insert( entry.second.repository_id );
|
||||
|
||||
for( const auto& entry : m_repository_list )
|
||||
{
|
||||
const wxString& repository_id = std::get<0>( entry );
|
||||
|
||||
if( repo_ids.count( repository_id ) == 0 )
|
||||
continue;
|
||||
|
||||
CacheRepository( repository_id );
|
||||
|
||||
if( m_statusReporter->IsCancelled() )
|
||||
break;
|
||||
}
|
||||
|
||||
if( m_statusReporter->IsCancelled() )
|
||||
return;
|
||||
|
||||
// Count packages with updates
|
||||
int availableUpdateCount = 0;
|
||||
|
||||
for( auto& entry : m_installed )
|
||||
{
|
||||
PCM_INSTALLATION_ENTRY& installed_package = entry.second;
|
||||
|
||||
if( m_repository_cache.find( installed_package.repository_id )
|
||||
!= m_repository_cache.end() )
|
||||
{
|
||||
PCM_PACKAGE_STATE state =
|
||||
GetPackageState( installed_package.repository_id,
|
||||
installed_package.package.identifier );
|
||||
|
||||
if( state == PPS_UPDATE_AVAILABLE )
|
||||
availableUpdateCount++;
|
||||
}
|
||||
|
||||
if( m_statusReporter->IsCancelled() )
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the badge on PCM button
|
||||
m_availableUpdateCallback( availableUpdateCount );
|
||||
|
||||
m_statusCallback( availableUpdateCount > 0 ? _( "Package updates are available" )
|
||||
: _( "No package updates available" ) );
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
void PLUGIN_CONTENT_MANAGER::StopBackgroundUpdate()
|
||||
{
|
||||
if( m_updateThread.joinable() )
|
||||
{
|
||||
m_statusReporter->Cancel();
|
||||
m_updateThread.join();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PLUGIN_CONTENT_MANAGER::~PLUGIN_CONTENT_MANAGER()
|
||||
{
|
||||
// By the time object is being destroyed the thread should be
|
||||
// stopped already but just in case do it here too.
|
||||
StopBackgroundUpdate();
|
||||
}
|
||||
|
|
|
@ -24,9 +24,11 @@
|
|||
#include "core/wx_stl_compat.h"
|
||||
#include "pcm_data.h"
|
||||
#include "widgets/wx_progress_reporters.h"
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <nlohmann/json-schema.hpp>
|
||||
#include <thread>
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
@ -74,6 +76,9 @@ typedef std::vector<std::pair<wxString, wxString>> STRING_PAIR_LIST;
|
|||
typedef std::vector<std::tuple<wxString, wxString, wxString>> STRING_TUPLE_LIST;
|
||||
|
||||
|
||||
class STATUS_TEXT_REPORTER;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Main class of Plugin and Content Manager subsystem
|
||||
*
|
||||
|
@ -96,9 +101,17 @@ typedef std::vector<std::tuple<wxString, wxString, wxString>> STRING_TUPLE_LIST;
|
|||
class PLUGIN_CONTENT_MANAGER
|
||||
{
|
||||
public:
|
||||
PLUGIN_CONTENT_MANAGER( wxWindow* aParent );
|
||||
PLUGIN_CONTENT_MANAGER( std::function<void( int )> aAvailableUpdateCallback,
|
||||
std::function<void( const wxString )> aStatusCallback );
|
||||
~PLUGIN_CONTENT_MANAGER();
|
||||
|
||||
/**
|
||||
* @brief Saves metadata of installed packages to disk
|
||||
*
|
||||
* Path is <user settings>/installed_packages.json
|
||||
*/
|
||||
void SaveInstalledPackages();
|
||||
|
||||
/**
|
||||
* @brief Fetches repository metadata from given url
|
||||
*
|
||||
|
@ -109,7 +122,7 @@ public:
|
|||
* @return false if URL could not be downloaded or result could not be parsed
|
||||
*/
|
||||
bool FetchRepository( const wxString& aUrl, PCM_REPOSITORY& aRepository,
|
||||
WX_PROGRESS_REPORTER* aReporter );
|
||||
PROGRESS_REPORTER* aReporter );
|
||||
|
||||
/**
|
||||
* @brief Validates json against a specific definition in the PCM schema
|
||||
|
@ -250,8 +263,8 @@ public:
|
|||
* @return false if download failed or was too large
|
||||
*/
|
||||
bool DownloadToStream( const wxString& aUrl, std::ostream* aOutput,
|
||||
WX_PROGRESS_REPORTER* aReporter,
|
||||
const size_t aSizeLimit = DEFAULT_DOWNLOAD_MEM_LIMIT );
|
||||
PROGRESS_REPORTER* aReporter,
|
||||
const size_t aSizeLimit = DEFAULT_DOWNLOAD_MEM_LIMIT );
|
||||
|
||||
/**
|
||||
* @brief Get the approximate measure of how much given package matches the search term
|
||||
|
@ -283,6 +296,32 @@ public:
|
|||
*/
|
||||
std::unordered_map<wxString, wxBitmap> GetInstalledPackageBitmaps();
|
||||
|
||||
/**
|
||||
* @brief Set the Dialog Window
|
||||
*
|
||||
* PCM can effectively run in "silent" mode with a background thread that
|
||||
* reports to kicad manager window status bar. Setting valid window pointer here
|
||||
* will switch it to GUI mode with WX_PROGRESS_DIALOG popup for downloads.
|
||||
*
|
||||
* @param aDialog parent dialog for progress window
|
||||
*/
|
||||
void SetDialogWindow( wxWindow* aDialog ) { m_dialog = aDialog; };
|
||||
|
||||
/**
|
||||
* @brief Runs a background update thread that checks for new package versions
|
||||
*/
|
||||
void RunBackgroundUpdate();
|
||||
|
||||
/**
|
||||
* @brief Interrupts and joins() the update thread
|
||||
*/
|
||||
void StopBackgroundUpdate();
|
||||
|
||||
/**
|
||||
* @brief Stores 3rdparty path from environment variables
|
||||
*/
|
||||
void ReadEnvVar();
|
||||
|
||||
private:
|
||||
///< Default download limit of 10 Mb to not use too much memory
|
||||
static constexpr size_t DEFAULT_DOWNLOAD_MEM_LIMIT = 10 * 1024 * 1024;
|
||||
|
@ -297,7 +336,7 @@ private:
|
|||
* @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, WX_PROGRESS_REPORTER* aReporter );
|
||||
std::vector<PCM_PACKAGE>& aPackages, PROGRESS_REPORTER* aReporter );
|
||||
|
||||
/**
|
||||
* @brief Get the cached repository metadata
|
||||
|
@ -307,6 +346,18 @@ private:
|
|||
*/
|
||||
const PCM_REPOSITORY& getCachedRepository( const wxString& aRepositoryId ) const;
|
||||
|
||||
/**
|
||||
* @brief Updates metadata of installed packages from freshly fetched repo
|
||||
*
|
||||
* This completely replaces all fields including description.
|
||||
* Only exception is versions field, if currently installed version is missing
|
||||
* from the repo metadata it is manually added back in to correctly display in the
|
||||
* installed packages.
|
||||
*
|
||||
* @param aRepositoryId
|
||||
*/
|
||||
void updateInstalledPackagesMetadata( const wxString& aRepositoryId );
|
||||
|
||||
/**
|
||||
* @brief Parses version strings and calculates compatibility
|
||||
*
|
||||
|
@ -329,6 +380,11 @@ private:
|
|||
// 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, int> m_kicad_version;
|
||||
std::function<void( int )> m_availableUpdateCallback;
|
||||
std::function<void( const wxString )> m_statusCallback;
|
||||
std::thread m_updateThread;
|
||||
|
||||
std::shared_ptr<STATUS_TEXT_REPORTER> m_statusReporter;
|
||||
};
|
||||
|
||||
#endif // PCM_H_
|
||||
|
|
|
@ -128,6 +128,8 @@ struct PCM_REPOSITORY
|
|||
|
||||
// Not serialized fields
|
||||
std::vector<PCM_PACKAGE> package_list;
|
||||
// pkg id to index of package from package_list for quick lookup
|
||||
std::unordered_map<wxString, size_t> package_map;
|
||||
};
|
||||
|
||||
|
||||
|
@ -139,6 +141,9 @@ struct PCM_INSTALLATION_ENTRY
|
|||
wxString repository_id;
|
||||
wxString repository_name;
|
||||
uint64_t install_timestamp;
|
||||
|
||||
// Not serialized fields
|
||||
bool update_available;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -806,7 +806,7 @@ int KICAD_MANAGER_CONTROL::ShowPluginManager( const TOOL_EVENT& aEvent )
|
|||
m_frame->SetFocus();
|
||||
wxSafeYield();
|
||||
|
||||
DIALOG_PCM pcm( m_frame );
|
||||
DIALOG_PCM pcm( m_frame, m_frame->GetPcm() );
|
||||
pcm.ShowModal();
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue